From 717489542601b7c3e8a05019c6762a38dfcf4b77 Mon Sep 17 00:00:00 2001 From: midilab Date: Thu, 24 Mar 2022 09:23:33 -0300 Subject: [PATCH] initial slave sync new implementation setup, need some tests and tunnings... --- src/uClock.cpp | 94 ++++++++++---------------------------------------- src/uClock.h | 21 +++-------- 2 files changed, 23 insertions(+), 92 deletions(-) diff --git a/src/uClock.cpp b/src/uClock.cpp index db7714b..62d1302 100755 --- a/src/uClock.cpp +++ b/src/uClock.cpp @@ -87,9 +87,6 @@ static inline uint16_t clock_diff(uint16_t old_clock, uint16_t new_clock) uClockClass::uClockClass() { - // drift is used to sligth calibrate with your slave clock - drift = 1; - slave_drift = 0; pll_x = 220; tempo = 120; start_timer = 0; @@ -97,7 +94,6 @@ uClockClass::uClockClass() sync_interval = 0; state = PAUSED; mode = INTERNAL_CLOCK; - ext_interval_acc = 0; resetCounters(); onClock96PPQNCallback = NULL; @@ -112,7 +108,6 @@ uClockClass::uClockClass() void uClockClass::init() { - // init work clock timer interrupt at 16 microseconds uclockInitTimer(); } @@ -156,14 +151,14 @@ void uClockClass::pause() void uClockClass::setTimerTempo(float bpm) { // 96 ppqn resolution - uint32_t tick_us_interval = (60000000 / 96 / bpm)*4; + tick_us_interval = (60000000 / 24 / bpm); + tick_hertz_interval = 1/((float)tick_us_interval/1000000); #if defined(TEENSYDUINO) && !defined(__AVR_ATmega32U4__) ATOMIC( _uclockTimer.update(tick_us_interval); ) #else - float tick_hertz_interval = 1/((float)tick_us_interval/1000000); uint32_t ocr; uint8_t tccr = 0; @@ -214,62 +209,9 @@ void uClockClass::setTempo(float bpm) float uClockClass::getTempo() { - if (mode == EXTERNAL_CLOCK) { - uint32_t acc = 0; - for (uint8_t i=0; i < EXT_INTERVAL_BUFFER_SIZE; i++) { - acc += ext_interval_buffer[i]; - } - if (acc != 0) { - // get average interval, because MIDI sync world is a wild place... - ////tempo = (float)((((float)FREQ_RESOLUTION/24) * 60) / (float)(acc / EXT_INTERVAL_BUFFER_SIZE)); - // derivated one time calc value = ( freq_resolution / 24 ) * 60 - //tempo = (float)(156250.0 / (acc / EXT_INTERVAL_BUFFER_SIZE)); - } - } return tempo; } -void uClockClass::setDrift(uint8_t value) -{ - ATOMIC(drift = value) - // force set tempo to update runtime interval - setTempo(tempo); -} - -void uClockClass::setSlaveDrift(uint8_t value) -{ - ATOMIC(slave_drift = value) -} - -uint8_t uClockClass::getDrift() -{ - return drift; -} - -// each interval is 16us -// this method is usefull for debug -uint16_t uClockClass::getInterval() -{ - return interval; -} - -// Main poolling tick call -uint8_t uClockClass::getTick(uint32_t * tick) -{ - ATOMIC( - uint32_t last_tick = internal_tick; - ) - if (*tick != last_tick) { - *tick = last_tick; - return 1; - } - if (last_tick - *tick > 1) { - *tick++; - return 1; - } - return 0; -} - void uClockClass::setMode(uint8_t tempo_mode) { mode = tempo_mode; @@ -292,14 +234,12 @@ void uClockClass::clockMe() void uClockClass::resetCounters() { counter = 0; - last_clock = 0; + external_clock = 0; internal_tick = 0; external_tick = 0; div32th_counter = 0; div16th_counter = 0; mod6_counter = 0; - inmod6_counter = 0; - ext_interval_idx = 0; } // TODO: Tap stuff @@ -316,8 +256,9 @@ void uClockClass::shuffle() void uClockClass::handleExternalClock() { - last_interval = clock_diff(last_clock, _clock); - last_clock = _clock; + uint32_t u_timer = micros(); + last_interval = clock_diff(external_clock, u_timer); + external_clock = u_timer; // slave tick me! external_tick++; @@ -331,12 +272,6 @@ void uClockClass::handleExternalClock() break; case STARTED: - // accumulate interval incomming ticks data for getTempo() smooth reads on slave mode - if(++ext_interval_idx >= EXT_INTERVAL_BUFFER_SIZE) { - ext_interval_idx = 0; - } - ext_interval_buffer[ext_interval_idx] = last_interval; - if (external_tick == 1) { interval = last_interval; } else { @@ -349,11 +284,9 @@ void uClockClass::handleExternalClock() void uClockClass::handleTimerInt() { //if (counter == 0) { - // update internal clock base counter + counter = interval; - // need a callback? - // please, use the polling method with getTick() instead... if (onClock96PPQNCallback) { onClock96PPQNCallback(&internal_tick); } @@ -381,7 +314,8 @@ void uClockClass::handleTimerInt() mod6_counter++; if (mode == EXTERNAL_CLOCK) { - sync_interval = clock_diff(last_clock, _clock); + uint32_t u_timer = micros(); + sync_interval = clock_diff(external_clock, u_timer); if ((internal_tick < external_tick) || (internal_tick > (external_tick + 1))) { internal_tick = external_tick; } @@ -392,6 +326,16 @@ void uClockClass::handleTimerInt() counter += phase_mult(counter - sync_interval); } } + + // update internal clock base counter + float diff = 1/((float)counter/1000000.0); + float bpm = (float)((float)(diff/24.0) * 60.0); + if (bpm != tempo) { + if (bpm > 1 && bpm < 300) { + tempo = bpm; + setTimerTempo(tempo); + } + } } if (mod6_counter == 6) { diff --git a/src/uClock.h b/src/uClock.h index 5cb9115..550fb0e 100755 --- a/src/uClock.h +++ b/src/uClock.h @@ -39,8 +39,6 @@ namespace umodular { namespace clock { #define PHASE_FACTOR 16 -#define EXT_INTERVAL_BUFFER_SIZE 24 - #define SECS_PER_MIN (60UL) #define SECS_PER_HOUR (3600UL) #define SECS_PER_DAY (SECS_PER_HOUR * 24L) @@ -64,9 +62,10 @@ class uClockClass { volatile uint32_t internal_tick; volatile uint32_t external_tick; - volatile uint16_t interval; - volatile uint16_t last_clock; - volatile uint8_t inmod6_counter; + volatile uint32_t interval; + volatile uint32_t external_clock; + uint32_t tick_us_interval; + float tick_hertz_interval; uint32_t div32th_counter; uint32_t div16th_counter; uint8_t mod6_counter; @@ -74,8 +73,6 @@ class uClockClass { uint16_t pll_x; uint32_t last_tick; - uint8_t drift; - uint8_t slave_drift; float tempo; uint32_t start_timer; uint8_t mode; @@ -83,11 +80,6 @@ class uClockClass { uint16_t last_interval; uint16_t sync_interval; - uint16_t ext_interval_buffer[EXT_INTERVAL_BUFFER_SIZE]; - uint32_t ext_interval_acc; - uint16_t ext_interval_idx; - - public: enum { @@ -136,11 +128,6 @@ class uClockClass { void pause(); void setTempo(float bpm); float getTempo(); - void setDrift(uint8_t value); - uint8_t getDrift(); - void setSlaveDrift(uint8_t value); - uint16_t getInterval(); - uint8_t getTick(uint32_t *_tick); // external timming control void setMode(uint8_t tempo_mode);