From c7b081954d92eebfa907e0c98e00eab9bc903f34 Mon Sep 17 00:00:00 2001 From: midilab Date: Sun, 16 Feb 2025 20:02:59 -0300 Subject: [PATCH] added input clock resolution other than 24ppqn --- src/uClock.cpp | 65 ++++++++++++++++++++++++++++++++++---------------- src/uClock.h | 14 ++++++++--- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/uClock.cpp b/src/uClock.cpp index c06a9fa..1d42175 100755 --- a/src/uClock.cpp +++ b/src/uClock.cpp @@ -130,8 +130,8 @@ uClockClass::uClockClass() onStepCallback = nullptr; onClockStartCallback = nullptr; onClockStopCallback = nullptr; - // first ppqn references calculus - setPPQN(PPQN_96); + // first ppqn references calculus for ppqn and clock resolution + calculateReferencedata(); } void uClockClass::init() @@ -146,15 +146,30 @@ uint32_t uClockClass::bpmToMicroSeconds(float bpm) return (60000000.0f / (float)ppqn / bpm); } +void uClockClass::calculateReferencedata() +{ + mod_clock_ref = ppqn / clock_ppqn; + mod_sync24_ref = ppqn / PPQN_24; + mod_step_ref = ppqn / 4; +} + void uClockClass::setPPQN(PPQNResolution resolution) { // stop clock to make it safe changing those references - // so we avoid volatile then and ATOMIC everyone + // so we avoid volatile then and ATOMIC everywhere stop(); ppqn = resolution; - // calculate the mod24 and mod_step tick reference trigger - mod24_ref = ppqn / 24; - mod_step_ref = ppqn / 4; + calculateReferencedata(); +} + +void uClockClass::setClockPPQN(PPQNResolution resolution) +{ + // stop clock to make it safe changing those references + // so we avoid volatile then and ATOMIC everywhere + stop(); + clock_ppqn = resolution; + calculateReferencedata(); + //mod_clock_ref = ppqn / clock_ppqn; } void uClockClass::start() @@ -238,7 +253,6 @@ void uClockClass::run() #endif } -// this function is based on sync24PPQN float inline uClockClass::freqToBpm(uint32_t freq) { float usecs = 1/((float)freq/1000000.0); @@ -268,8 +282,10 @@ void uClockClass::resetCounters() { tick = 0; int_clock_tick = 0; - mod24_counter = 0; + sync24_tick = 0; + mod_clock_counter = 0; mod_step_counter = 0; + mod_sync24_counter = 0; step_counter = 0; ext_clock_tick = 0; ext_clock_us = 0; @@ -371,7 +387,7 @@ bool inline uClockClass::processShuffle() return false; } -// it is expected to be called in 24PPQN +// TODO: needs to check clock signals against current phase lock parameters(based on 24ppqn sync) void uClockClass::handleExternalClock() { switch (state) { @@ -408,19 +424,19 @@ void uClockClass::handleExternalClock() void uClockClass::handleTimerInt() { - // reset mod24 counter reference ? - if (mod24_counter == mod24_ref) - mod24_counter = 0; + // reset mod_clock_counter + if (mod_clock_counter == mod_clock_ref) + mod_clock_counter = 0; // process sync signals first please... - if (mod24_counter == 0) { + if (mod_clock_counter == 0) { if (mode == EXTERNAL_CLOCK) { // sync tick position with external tick clock if ((int_clock_tick < ext_clock_tick) || (int_clock_tick > (ext_clock_tick + 1))) { int_clock_tick = ext_clock_tick; - tick = int_clock_tick * mod24_ref; - mod24_counter = tick % mod24_ref; + tick = int_clock_tick * mod_clock_ref; + mod_clock_counter = tick % mod_clock_ref; mod_step_counter = tick % mod_step_ref; } @@ -446,13 +462,21 @@ void uClockClass::handleTimerInt() } } - if (onSync24Callback) { - onSync24Callback(int_clock_tick); - } - // internal clock tick me! sync24 tick too + // internal clock tick me! ++int_clock_tick; } + // Sync24 callback + if (mod_sync24_counter == mod_sync24_ref) + mod_sync24_counter = 0; + + if (onSync24Callback) { + if (mod_sync24_counter == 0) { + onSync24Callback(sync24_tick); + ++sync24_tick; + } + } + // PPQNCallback time! if (onPPQNCallback) { onPPQNCallback(tick); @@ -476,7 +500,8 @@ void uClockClass::handleTimerInt() // tick me! ++tick; // increment mod counters - ++mod24_counter; + ++mod_clock_counter; + ++mod_sync24_counter; ++mod_step_counter; } diff --git a/src/uClock.h b/src/uClock.h index 45f0899..b720839 100755 --- a/src/uClock.h +++ b/src/uClock.h @@ -84,6 +84,9 @@ class uClockClass { }; enum PPQNResolution { + PPQN_4 = 4, + PPQN_8 = 8, + PPQN_12 = 12, PPQN_24 = 24, PPQN_48 = 48, PPQN_96 = 96, @@ -118,6 +121,7 @@ class uClockClass { void init(); void setPPQN(PPQNResolution resolution); + void setClockPPQN(PPQNResolution resolution); void handleTimerInt(); void handleExternalClock(); @@ -162,6 +166,7 @@ class uClockClass { private: float inline freqToBpm(uint32_t freq); + void calculateReferencedata(); // shuffle bool inline processShuffle(); @@ -175,14 +180,17 @@ class uClockClass { // internal clock control // uint16_t ppqn; PPQNResolution ppqn = PPQN_96; + PPQNResolution clock_ppqn = PPQN_24; uint32_t tick; uint32_t int_clock_tick; - uint8_t mod24_counter; - uint8_t mod24_ref; + uint32_t sync24_tick; + uint8_t mod_clock_counter; + uint8_t mod_clock_ref; uint8_t mod_step_counter; uint8_t mod_step_ref; uint32_t step_counter; // should we go uint16_t? - + uint8_t mod_sync24_counter; + uint8_t mod_sync24_ref; // external clock control volatile uint32_t ext_clock_us; volatile uint32_t ext_clock_tick;