Merge pull request #57 from midilab/develop

v2.3.0
main
midilab 1 week ago committed by GitHub
commit 8a4b45cf90
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 89
      README.md
  2. 12
      examples/AVRUartSlaveMidiClockMonitor/AVRUartSlaveMidiClockMonitor.ino
  3. 6
      examples/AcidStepSequencer/AcidStepSequencer.ino
  4. 6
      examples/ESP32UartMasterMidiClock/ESP32UartMasterMidiClock.ino
  5. 17
      examples/GenericMasterOrExternalSync/GenericMasterOrExternalSync.ino
  6. 12
      examples/LeonardoUsbSlaveMidiClockMonitor/LeonardoUsbSlaveMidiClockMonitor.ino
  7. 6
      examples/MidiClock/MidiClock.ino
  8. 6
      examples/RP2040UsbUartMasterClock/RP2040UsbUartMasterClock.ino
  9. 6
      examples/STM32UartMasterMidiClock/STM32UartMasterMidiClock.ino
  10. 6
      examples/TeensyUsbMasterMidiClock/TeensyUsbMasterMidiClock.ino
  11. 8
      examples/TeensyUsbSlaveMidiClock/TeensyUsbSlaveMidiClock.ino
  12. 12
      examples/TeensyUsbSlaveMidiClockMonitor/TeensyUsbSlaveMidiClockMonitor.ino
  13. 6
      examples/XiaoUsbMasterMidiClock/XiaoUsbMasterMidiClock.ino
  14. 32
      src/uClock.cpp
  15. 16
      src/uClock.h

@ -11,15 +11,23 @@ With uClock, you can create professional-grade sequencers, sync boxes, or genera
## Interface ## Interface
The uClock library API operates through an attached callback function mechanism: The uClock library API operates through an attached callback function mechanism:
1. **setOnOutputPPQN(onPPQNCallback) > onOutputPPQNCallback(uint32_t tick)** Calls are made on each new output pulse based on the selected PPQN resolution (if no PPQN is set, the default is 96 PPQN). 1. **setOnOutputPPQN(onPPQNCallback) > onOutputPPQNCallback(uint32_t tick)** Callback are made on each new output pulse based on the selected PPQN resolution (if no PPQN is set, the default is 96 PPQN).
2. **setOnInputPPQN(onPPQNCallback) > onInputPPQNCallback(uint32_t tick)** Set the expected input PPQN (Pulses Per Quarter Note) resolution for external clock sync. 2. **setOnStep(onStepCallback) > onStepCallback(uint32_t step)** A good way to code an old-style step sequencer based on a 16th-note schema, which is not dependent on PPQN (Pulses Per Quarter Note) output config.
3. **setOnStep(onStepCallback) > onStepCallback(uint32_t step)** A good way to code an old-style step sequencer based on a 16th-note schema, which is not dependent on PPQN (Pulses Per Quarter Note) output config. 3. **setOnSync24(onSync24Callback) > onSync24Callback(uint32_t tick)** A good way to code a clock machine or keep your devices in sync with your system is to use setOnSyncXX(), where XX represents the PPQN (Pulses Per Quarter Note) value you want to use. MIDI specifications typically expect 24 PPQN, but if you're working with other devices that are not MIDI standard, you can choose a different PPQN value. Please refer to the supported PPQNs to select from. You can use one or more setOnSyncXX callbacks for different sync output signatures.
4. **setOnSync24(onSync24Callback) > onSync24Callback(uint32_t tick)** A good way to code a clock machine or keep your devices in sync with your system is to use setOnSyncXX(), where XX represents the PPQN (Pulses Per Quarter Note) value you want to use. MIDI specifications typically expect 24 PPQN, but if you're working with other devices that are not MIDI standard, you can choose a different PPQN value. Please refer to the supported PPQNs to select from. You can use one or more setOnSyncXX callbacks for different sync output signatures. 4. **setOnClockStart(onClockStartCallback) > onClockStartCallback()** On the uClock Start event.
5. **setOnClockStart(onClockStartCallback) > onClockStartCallback()** On the uClock Start event. 5. **setOnClockStop(onClockStopCallback) > onClockStopCallback()** On the uClock Stop event.
6. **setOnClockStop(onClockStopCallback) > onClockStopCallback()** On the uClock Stop event.
### Clock input/output resolutions ### Clock input/output resolutions
You can setup multiple clock resolutions for clock generation and clock sync signals.
#### Set internal output clock and external input clock resolution
1. **void setOutputPPQN(PPQNResolution resolution);** sets the main clock output(independent from clock input).
2. **void setInputPPQN(PPQNResolution resolution);** sets the expected external clock resolution for input(independent from clock output).
#### PPQNResolution Avaliable Resolutions
1. **PPQN_1** 1 Pulses Per Quarter Note (only input) 1. **PPQN_1** 1 Pulses Per Quarter Note (only input)
2. **PPQN_2** 2 Pulses Per Quarter Note (only input) 2. **PPQN_2** 2 Pulses Per Quarter Note (only input)
3. **PPQN_4** 4 Pulses Per Quarter Note 3. **PPQN_4** 4 Pulses Per Quarter Note
@ -82,7 +90,7 @@ You will find more complete examples on examples/ folder:
bool _external_sync_on = false; bool _external_sync_on = false;
// the main uClock PPQN resolution ticking // the main uClock PPQN resolution ticking
void onPPQNCallback(uint32_t tick) { void onOutputPPQNCallback(uint32_t tick) {
// tick your sequencers or tickable devices... // tick your sequencers or tickable devices...
} }
@ -90,11 +98,31 @@ void onStepCallback(uint32_t step) {
// triger step data for sequencer device... // triger step data for sequencer device...
} }
// The callback function called by uClock each Pulse of 1PPQN clock resolution.
void onSync1Callback(uint32_t tick) {
// send sync signal to...
}
// The callback function called by uClock each Pulse of 2PPQN clock resolution.
void onSync2Callback(uint32_t tick) {
// send sync signal to...
}
// The callback function called by uClock each Pulse of 4PPQN clock resolution.
void onSync4Callback(uint32_t tick) {
// send sync signal to...
}
// The callback function called by uClock each Pulse of 24PPQN clock resolution. // The callback function called by uClock each Pulse of 24PPQN clock resolution.
void onSync24Callback(uint32_t tick) { void onSync24Callback(uint32_t tick) {
// send sync signal to... // send sync signal to...
} }
// The callback function called by uClock each Pulse of 48PPQN clock resolution.
void onSync48Callback(uint32_t tick) {
// send sync signal to...
}
// The callback function called when clock starts by using uClock.start() method. // The callback function called when clock starts by using uClock.start() method.
void onClockStartCallback() { void onClockStartCallback() {
// send start signal to... // send start signal to...
@ -106,28 +134,41 @@ void onClockStopCallback() {
} }
void setup() { void setup() {
// setup clock library
// inits the clock library // avaliable output resolutions
uClock.init(); // [ uClock.PPQN_4, uClock.PPQN_8, uClock.PPQN_12, uClock.PPQN_24, uClock.PPQN_48, uClock.PPQN_96, uClock.PPQN_384, uClock.PPQN_480, uClock.PPQN_960 ]
// avaliable resolutions
// [ uClock.PPQN_24, uClock.PPQN_48, uClock.PPQN_96, uClock.PPQN_384, uClock.PPQN_480, uClock.PPQN_960 ]
// not mandatory to call, the default is 96PPQN if not set // not mandatory to call, the default is 96PPQN if not set
uClock.setPPQN(uClock.PPQN_96); uClock.setOutputPPQN(uClock.PPQN_96);
// you need to use at least one! // you need to use at least one!
uClock.setOnOutputPPQN(onPPQNCallback); uClock.setOnOutputPPQN(onOutputPPQNCallback);
uClock.setOnStep(onStepCallback); uClock.setOnStep(onStepCallback);
// multi sync output signatures avaliable
// normaly used by eurorack modular modules
uClock.setOnSync1(onSync1Callback);
uClock.setOnSync2(onSync2Callback);
uClock.setOnSync4(onSync4Callback);
// midi sync standard
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// some korg machines do 48ppqn
uClock.setOnSync48(onSync48Callback);
uClock.setOnClockStart(onClockStartCallback); uClock.setOnClockStart(onClockStartCallback);
uClock.setOnClockStop(onClockStopCallback); uClock.setOnClockStop(onClockStopCallback);
// set external sync mode? // set external sync mode?
if (_external_sync_on) { if (_external_sync_on) {
uClock.setMode(uClock.EXTERNAL_CLOCK); uClock.setClockMode(uClock.EXTERNAL_CLOCK);
// what is the clock of incomming signal to sync with?
// not mandatory to call, the default is 24PPQN if not set
// avaliable input resolutions - should be always InputPPQN <= OutputPPQN
// [ uClock.PPQN_1, uClock.PPQN_2, uClock.PPQN_4, uClock.PPQN_8, uClock.PPQN_12, uClock.PPQN_24, uClock.PPQN_48, uClock.PPQN_96, uClock.PPQN_384, uClock.PPQN_480, uClock.PPQN_960 ]
uClock.setInputPPQN(uClock.PPQN_24);
} }
// inits the clock library
uClock.init();
// starts clock // starts clock
uClock.start(); uClock.start();
} }
@ -184,8 +225,6 @@ void setup() {
// Initialize serial communication at 31250 bits per second, the default MIDI serial speed communication: // Initialize serial communication at 31250 bits per second, the default MIDI serial speed communication:
Serial.begin(31250); Serial.begin(31250);
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message based on 24PPQN // Set the callback function for the clock output to send MIDI Sync message based on 24PPQN
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// Set the callback function for MIDI Start and Stop messages. // Set the callback function for MIDI Start and Stop messages.
@ -194,6 +233,9 @@ void setup() {
// Set the clock BPM to 126 BPM // Set the clock BPM to 126 BPM
uClock.setTempo(126); uClock.setTempo(126);
// Inits the clock
uClock.init();
// Starts the clock, tick-tac-tick-tac... // Starts the clock, tick-tac-tick-tac...
uClock.start(); uClock.start();
@ -227,8 +269,6 @@ void onClockStop() {
} }
void setup() { void setup() {
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. based on 24PPQN // Set the callback function for the clock output to send MIDI Sync message. based on 24PPQN
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// Set the callback function for MIDI Start and Stop messages. // Set the callback function for MIDI Start and Stop messages.
@ -236,6 +276,9 @@ void setup() {
uClock.setOnClockStopOutput(onClockStop); uClock.setOnClockStopOutput(onClockStop);
// Set the clock BPM to 126 BPM // Set the clock BPM to 126 BPM
uClock.setTempo(126); uClock.setTempo(126);
// Inits the clock
uClock.init();
// Starts the clock, tick-tac-tick-tac... // Starts the clock, tick-tac-tick-tac...
uClock.start(); uClock.start();
} }
@ -395,9 +438,6 @@ void setup()
// the default MIDI serial speed communication at 31250 bits per second // the default MIDI serial speed communication at 31250 bits per second
Serial.begin(31250); Serial.begin(31250);
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. // Set the callback function for the clock output to send MIDI Sync message.
uClock.setOnOutputPPQN(onPPQNCallback); uClock.setOnOutputPPQN(onPPQNCallback);
@ -428,6 +468,9 @@ void setup()
// pins, buttons, leds and pots config // pins, buttons, leds and pots config
//configureYourUserInterface(); //configureYourUserInterface();
// Inits the clock
uClock.init();
// start sequencer // start sequencer
uClock.start(); uClock.start();
} }

@ -111,12 +111,20 @@ void setup() {
// //
// uClock Setup // uClock Setup
// //
uClock.init();
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// For MIDI Sync Start and Stop // For MIDI Sync Start and Stop
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
uClock.setMode(uClock.EXTERNAL_CLOCK); uClock.setClockMode(uClock.EXTERNAL_CLOCK);
// for smooth slave tempo calculate display you should raise the
// buffer_size of ext_interval_buffer in between 64 to 128. 254 max size.
// note: this doesn't impact on sync time, only display time getTempo()
// if you dont want to use it, it is default set it to 1 for memory save
uClock.setExtIntervalBuffer(128);
// inits uClock
uClock.init();
//uClock.setTempo(136.5); //uClock.setTempo(136.5);
//uClock.start(); //uClock.start();
} }

@ -154,9 +154,6 @@ void setup()
Serial.begin(115200); Serial.begin(115200);
#endif #endif
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. // Set the callback function for the clock output to send MIDI Sync message.
uClock.setOnOutputPPQN(onOutputPPQNCallback); uClock.setOnOutputPPQN(onOutputPPQNCallback);
@ -170,6 +167,9 @@ void setup()
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
// Inits the clock
uClock.init();
// Set the clock BPM to 126 BPM // Set the clock BPM to 126 BPM
uClock.setTempo(126); uClock.setTempo(126);

@ -56,13 +56,15 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
// Setup our clock system // Setup our clock system
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. // Set the callback function for the clock output to send MIDI Sync message.
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// Set the callback function for MIDI Start and Stop messages. // Set the callback function for MIDI Start and Stop messages.
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
// Inits the clock
uClock.init();
// Set the clock BPM to 126 BPM // Set the clock BPM to 126 BPM
uClock.setTempo(126); uClock.setTempo(126);
// Starts the clock, tick-tac-tick-tac... // Starts the clock, tick-tac-tick-tac...

@ -48,12 +48,9 @@ void onClockStopCallback() {
} }
void setup() { void setup() {
// setup clock library
// inits the clock library // avaliable output resolutions
uClock.init(); // [ uClock.PPQN_4, uClock.PPQN_8, uClock.PPQN_12, uClock.PPQN_24, uClock.PPQN_48, uClock.PPQN_96, uClock.PPQN_384, uClock.PPQN_480, uClock.PPQN_960 ]
// avaliable output PPQN resolutions for this example
// [ uClock.PPQN_48, uClock.PPQN_96, uClock.PPQN_384, uClock.PPQN_480, uClock.PPQN_960 ]
// not mandatory to call, the default is 96PPQN if not set // not mandatory to call, the default is 96PPQN if not set
uClock.setOutputPPQN(uClock.PPQN_96); uClock.setOutputPPQN(uClock.PPQN_96);
@ -76,8 +73,16 @@ void setup() {
// set external sync mode? // set external sync mode?
if (_external_sync_on) { if (_external_sync_on) {
uClock.setClockMode(uClock.EXTERNAL_CLOCK); uClock.setClockMode(uClock.EXTERNAL_CLOCK);
// what is the clock of incomming signal to sync with?
// not mandatory to call, the default is 24PPQN if not set
// avaliable input resolutions - should be always InputPPQN <= OutputPPQN
// [ uClock.PPQN_1, uClock.PPQN_2, uClock.PPQN_4, uClock.PPQN_8, uClock.PPQN_12, uClock.PPQN_24, uClock.PPQN_48, uClock.PPQN_96, uClock.PPQN_384, uClock.PPQN_480, uClock.PPQN_960 ]
uClock.setInputPPQN(uClock.PPQN_24);
} }
// inits the clock library
uClock.init();
// starts clock // starts clock
uClock.start(); uClock.start();
} }

@ -102,12 +102,20 @@ void setup() {
// //
// uClock Setup // uClock Setup
// //
uClock.init();
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// For MIDI Sync Start and Stop // For MIDI Sync Start and Stop
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
uClock.setMode(uClock.EXTERNAL_CLOCK); uClock.setClockMode(uClock.EXTERNAL_CLOCK);
// for smooth slave tempo calculate display you should raise the
// buffer_size of ext_interval_buffer in between 64 to 128. 254 max size.
// note: this doesn't impact on sync time, only display time getTempo()
// if you dont want to use it, it is default set it to 1 for memory save
uClock.setExtIntervalBuffer(128);
// init uClock
uClock.init();
//uClock.setTempo(136.5); //uClock.setTempo(136.5);
//uClock.start(); //uClock.start();
} }

@ -31,13 +31,15 @@ void setup()
// Initialize serial communication at 31250 bits per second, the default MIDI serial speed communication: // Initialize serial communication at 31250 bits per second, the default MIDI serial speed communication:
Serial.begin(31250); Serial.begin(31250);
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. // Set the callback function for the clock output to send MIDI Sync message.
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// Set the callback function for MIDI Start and Stop messages. // Set the callback function for MIDI Start and Stop messages.
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
// Inits the clock
uClock.init();
// Set the clock BPM to 126 BPM // Set the clock BPM to 126 BPM
uClock.setTempo(126); uClock.setTempo(126);

@ -68,13 +68,15 @@ void setup() {
initBlinkLed(); initBlinkLed();
// Setup our clock system // Setup our clock system
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. // Set the callback function for the clock output to send MIDI Sync message.
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// Set the callback function for MIDI Start and Stop messages. // Set the callback function for MIDI Start and Stop messages.
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
// Inits the clock
uClock.init();
// Set the clock BPM to 126 BPM // Set the clock BPM to 126 BPM
uClock.setTempo(126); uClock.setTempo(126);
// Starts the clock, tick-tac-tick-tac.. // Starts the clock, tick-tac-tick-tac..

@ -64,13 +64,15 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
// Setup our clock system // Setup our clock system
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. // Set the callback function for the clock output to send MIDI Sync message.
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// Set the callback function for MIDI Start and Stop messages. // Set the callback function for MIDI Start and Stop messages.
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
// Inits the clock
uClock.init();
// Set the clock BPM to 126 BPM // Set the clock BPM to 126 BPM
uClock.setTempo(120); uClock.setTempo(120);
// Starts the clock, tick-tac-tick-tac... // Starts the clock, tick-tac-tick-tac...

@ -55,13 +55,15 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
// Setup our clock system // Setup our clock system
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. // Set the callback function for the clock output to send MIDI Sync message.
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// Set the callback function for MIDI Start and Stop messages. // Set the callback function for MIDI Start and Stop messages.
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
// Inits the clock
uClock.init();
// Set the clock BPM to 126 BPM // Set the clock BPM to 126 BPM
uClock.setTempo(126); uClock.setTempo(126);
// Starts the clock, tick-tac-tick-tac... // Starts the clock, tick-tac-tick-tac...

@ -76,15 +76,17 @@ void setup() {
usbMIDI.setHandleStop(onExternalStop); usbMIDI.setHandleStop(onExternalStop);
// Setup our clock system // Setup our clock system
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. // Set the callback function for the clock output to send MIDI Sync message.
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// Set the callback function for MIDI Start and Stop messages. // Set the callback function for MIDI Start and Stop messages.
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
// set to external sync mode // set to external sync mode
uClock.setMode(1); uClock.setClockMode(uClock.EXTERNAL_CLOCK);
// Inits the clock
uClock.init();
} }
void loop() { void loop() {

@ -109,12 +109,20 @@ void setup() {
// uClock Setup // uClock Setup
// //
// Setup our clock system // Setup our clock system
uClock.init();
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// For MIDI Sync Start and Stop // For MIDI Sync Start and Stop
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
uClock.setMode(uClock.EXTERNAL_CLOCK); uClock.setClockMode(uClock.EXTERNAL_CLOCK);
// for smooth slave tempo calculate display you should raise the
// buffer_size of ext_interval_buffer in between 64 to 128. 254 max size.
// note: this doesn't impact on sync time, only display time getTempo()
// if you dont want to use it, it is default set it to 1 for memory save
uClock.setExtIntervalBuffer(128);
// inits uClock
uClock.init();
// make use of 250us timer to handle midi input sync // make use of 250us timer to handle midi input sync
teensyTimer.begin(handleMidiInput, 250); teensyTimer.begin(handleMidiInput, 250);
teensyTimer.priority(80); teensyTimer.priority(80);

@ -54,13 +54,15 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
// Setup our clock system // Setup our clock system
// Inits the clock
uClock.init();
// Set the callback function for the clock output to send MIDI Sync message. // Set the callback function for the clock output to send MIDI Sync message.
uClock.setOnSync24(onSync24Callback); uClock.setOnSync24(onSync24Callback);
// Set the callback function for MIDI Start and Stop messages. // Set the callback function for MIDI Start and Stop messages.
uClock.setOnClockStart(onClockStart); uClock.setOnClockStart(onClockStart);
uClock.setOnClockStop(onClockStop); uClock.setOnClockStop(onClockStop);
// Inits the clock
uClock.init();
// Set the clock BPM to 126 BPM // Set the clock BPM to 126 BPM
uClock.setTempo(126); uClock.setTempo(126);
// Starts the clock, tick-tac-tick-tac... // Starts the clock, tick-tac-tick-tac...

@ -142,6 +142,9 @@ uClockClass::uClockClass()
void uClockClass::init() void uClockClass::init()
{ {
if (ext_interval_buffer == nullptr)
setExtIntervalBuffer(1);
uclockInitTimer(); uclockInitTimer();
// first interval calculus // first interval calculus
setTempo(tempo); setTempo(tempo);
@ -244,14 +247,14 @@ float uClockClass::getTempo()
if (clock_mode == EXTERNAL_CLOCK) { if (clock_mode == EXTERNAL_CLOCK) {
uint32_t acc = 0; uint32_t acc = 0;
// wait the buffer to get full // wait the buffer to get full
if (ext_interval_buffer[EXT_INTERVAL_BUFFER_SIZE-1] == 0) { if (ext_interval_buffer[ext_interval_buffer_size-1] == 0) {
return tempo; return tempo;
} }
for (uint8_t i=0; i < EXT_INTERVAL_BUFFER_SIZE; i++) { for (uint8_t i=0; i < ext_interval_buffer_size; i++) {
acc += ext_interval_buffer[i]; acc += ext_interval_buffer[i];
} }
if (acc != 0) { if (acc != 0) {
return freqToBpm(acc / EXT_INTERVAL_BUFFER_SIZE); return constrainBpm(freqToBpm(acc / ext_interval_buffer_size));
} }
} }
return tempo; return tempo;
@ -272,6 +275,11 @@ float inline uClockClass::freqToBpm(uint32_t freq)
return (float)((float)(usecs/(float)input_ppqn) * 60.0); return (float)((float)(usecs/(float)input_ppqn) * 60.0);
} }
float inline uClockClass::constrainBpm(float bpm)
{
return (bpm < MIN_BPM) ? MIN_BPM : ( bpm > MAX_BPM ? MAX_BPM : bpm );
}
void uClockClass::setClockMode(ClockMode tempo_mode) void uClockClass::setClockMode(ClockMode tempo_mode)
{ {
clock_mode = tempo_mode; clock_mode = tempo_mode;
@ -291,6 +299,16 @@ void uClockClass::clockMe()
} }
} }
void uClockClass::setExtIntervalBuffer(uint8_t buffer_size)
{
if (ext_interval_buffer != nullptr)
return;
// alloc once and forever policy
ext_interval_buffer_size = buffer_size;
ext_interval_buffer = (uint32_t*) malloc( sizeof(uint32_t) * ext_interval_buffer_size );
}
void uClockClass::resetCounters() void uClockClass::resetCounters()
{ {
tick = 0; tick = 0;
@ -317,7 +335,7 @@ void uClockClass::resetCounters()
mod_sync48_counter = 0; mod_sync48_counter = 0;
sync48_tick = 0; sync48_tick = 0;
for (uint8_t i=0; i < EXT_INTERVAL_BUFFER_SIZE; i++) { for (uint8_t i=0; i < ext_interval_buffer_size; i++) {
ext_interval_buffer[i] = 0; ext_interval_buffer[i] = 0;
} }
} }
@ -434,7 +452,7 @@ void uClockClass::handleExternalClock()
ext_clock_tick++; ext_clock_tick++;
// accumulate interval incomming ticks data for getTempo() smooth reads on slave clock_mode // accumulate interval incomming ticks data for getTempo() smooth reads on slave clock_mode
if(++ext_interval_idx >= EXT_INTERVAL_BUFFER_SIZE) { if(++ext_interval_idx >= ext_interval_buffer_size) {
ext_interval_idx = 0; ext_interval_idx = 0;
} }
ext_interval_buffer[ext_interval_idx] = last_interval; ext_interval_buffer[ext_interval_idx] = last_interval;
@ -479,14 +497,12 @@ void uClockClass::handleTimerInt()
} }
// update internal clock timer frequency // update internal clock timer frequency
float bpm = freqToBpm(counter); float bpm = constrainBpm(freqToBpm(counter));
if (bpm != tempo) { if (bpm != tempo) {
if (bpm >= MIN_BPM && bpm <= MAX_BPM) {
tempo = bpm; tempo = bpm;
setTimerTempo(bpm); setTimerTempo(bpm);
} }
} }
}
// internal clock tick me! // internal clock tick me!
++int_clock_tick; ++int_clock_tick;

@ -45,12 +45,6 @@ typedef struct {
int8_t step[MAX_SHUFFLE_TEMPLATE_SIZE] = {0}; int8_t step[MAX_SHUFFLE_TEMPLATE_SIZE] = {0};
} SHUFFLE_TEMPLATE; } SHUFFLE_TEMPLATE;
// for smooth slave tempo calculate display you should raise this value
// in between 64 to 128.
// note: this doesn't impact on sync time, only display time getTempo()
// if you dont want to use it, set it to 1 for memory save
#define EXT_INTERVAL_BUFFER_SIZE 128
#define MIN_BPM 1 #define MIN_BPM 1
#define MAX_BPM 400 #define MAX_BPM 400
@ -160,6 +154,11 @@ class uClockClass {
void setClockMode(ClockMode tempo_mode); void setClockMode(ClockMode tempo_mode);
ClockMode getClockMode(); ClockMode getClockMode();
void clockMe(); void clockMe();
// for smooth slave tempo calculate display you should raise the
// buffer_size of ext_interval_buffer in between 64 to 128. 254 max size.
// note: this doesn't impact on sync time, only display time getTempo()
// if you dont want to use it, it is default set it to 1 for memory save
void setExtIntervalBuffer(uint8_t buffer_size);
// shuffle // shuffle
void setShuffle(bool active); void setShuffle(bool active);
@ -185,6 +184,7 @@ class uClockClass {
private: private:
float inline freqToBpm(uint32_t freq); float inline freqToBpm(uint32_t freq);
float inline constrainBpm(float bpm);
void calculateReferencedata(); void calculateReferencedata();
// shuffle // shuffle
@ -246,7 +246,8 @@ class uClockClass {
uint32_t start_timer; uint32_t start_timer;
ClockMode clock_mode; ClockMode clock_mode;
volatile uint32_t ext_interval_buffer[EXT_INTERVAL_BUFFER_SIZE]; volatile uint32_t * ext_interval_buffer = nullptr;
uint8_t ext_interval_buffer_size;
uint16_t ext_interval_idx; uint16_t ext_interval_idx;
// shuffle implementation // shuffle implementation
@ -265,4 +266,3 @@ extern "C" {
} }
#endif /* __U_CLOCK_H__ */ #endif /* __U_CLOCK_H__ */

Loading…
Cancel
Save