tests and tunning for external sync and phase_mult system

pull/5/head
midilab 3 years ago
parent 7174895426
commit 59cd1c7e18
  1. 158
      src/uClock.cpp
  2. 29
      src/uClock.h

@ -76,12 +76,12 @@ static inline uint32_t phase_mult(uint32_t val)
return (val * PHASE_FACTOR) >> 8; return (val * PHASE_FACTOR) >> 8;
} }
static inline uint16_t clock_diff(uint16_t old_clock, uint16_t new_clock) static inline uint16_t clock_diff(uint32_t old_clock, uint32_t new_clock)
{ {
if (new_clock >= old_clock) { if (new_clock >= old_clock) {
return new_clock - old_clock; return new_clock - old_clock;
} else { } else {
return new_clock + (65535 - old_clock); return new_clock + (4294967295 - old_clock);
} }
} }
@ -207,8 +207,23 @@ void uClockClass::setTempo(float bpm)
tempo = bpm; tempo = bpm;
} }
float inline uClockClass::freqToBpm(uint32_t freq)
{
float usecs = 1/((float)freq/1000000.0);
return (float)((float)(usecs/24.0) * 60.0);
}
float uClockClass::getTempo() 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) {
return freqToBpm(acc / EXT_INTERVAL_BUFFER_SIZE);
}
}
return tempo; return tempo;
} }
@ -239,7 +254,11 @@ void uClockClass::resetCounters()
external_tick = 0; external_tick = 0;
div32th_counter = 0; div32th_counter = 0;
div16th_counter = 0; div16th_counter = 0;
mod6_counter = 0; mod6_counter = 0;
indiv32th_counter = 0;
indiv16th_counter = 0;
inmod6_counter = 0;
ext_interval_idx = 0;
} }
// TODO: Tap stuff // TODO: Tap stuff
@ -256,12 +275,6 @@ void uClockClass::shuffle()
void uClockClass::handleExternalClock() void uClockClass::handleExternalClock()
{ {
uint32_t u_timer = micros();
last_interval = clock_diff(external_clock, u_timer);
external_clock = u_timer;
// slave tick me!
external_tick++;
switch (state) { switch (state) {
case PAUSED: case PAUSED:
@ -272,6 +285,34 @@ void uClockClass::handleExternalClock()
break; break;
case STARTED: case STARTED:
uint32_t u_timer = micros();
last_interval = clock_diff(external_clock, u_timer);
external_clock = u_timer;
if (inmod6_counter == 0) {
indiv16th_counter++;
indiv32th_counter++;
}
if (inmod6_counter == 3) {
indiv32th_counter++;
}
// slave tick me!
external_tick++;
inmod6_counter++;
if (inmod6_counter == 6) {
inmod6_counter = 0;
}
// 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) { if (external_tick == 1) {
interval = last_interval; interval = last_interval;
} else { } else {
@ -283,68 +324,67 @@ void uClockClass::handleExternalClock()
void uClockClass::handleTimerInt() void uClockClass::handleTimerInt()
{ {
//if (counter == 0) { counter = interval;
if ((internal_tick < external_tick) || (internal_tick > (external_tick + 1))) {
internal_tick = external_tick;
div32th_counter = indiv32th_counter;
div16th_counter = indiv16th_counter;
mod6_counter = inmod6_counter;
}
counter = interval; if (onClock96PPQNCallback) {
onClock96PPQNCallback(&internal_tick);
}
if (onClock96PPQNCallback) { if (mod6_counter == 0) {
onClock96PPQNCallback(&internal_tick); if (onClock32PPQNCallback) {
onClock32PPQNCallback(&div32th_counter);
} }
if (onClock16PPQNCallback) {
if (mod6_counter == 0) { onClock16PPQNCallback(&div16th_counter);
if (onClock32PPQNCallback) {
onClock32PPQNCallback(&div32th_counter);
}
if (onClock16PPQNCallback) {
onClock16PPQNCallback(&div16th_counter);
}
div16th_counter++;
div32th_counter++;
} }
div16th_counter++;
div32th_counter++;
}
if (mod6_counter == 3) { if (mod6_counter == 3) {
if (onClock32PPQNCallback) { if (onClock32PPQNCallback) {
onClock32PPQNCallback(&div32th_counter); onClock32PPQNCallback(&div32th_counter);
}
div32th_counter++;
} }
div32th_counter++;
}
// tick me! // tick me!
internal_tick++; internal_tick++;
mod6_counter++; mod6_counter++;
if (mode == EXTERNAL_CLOCK) { if (mod6_counter == 6) {
uint32_t u_timer = micros(); mod6_counter = 0;
sync_interval = clock_diff(external_clock, u_timer); }
if ((internal_tick < external_tick) || (internal_tick > (external_tick + 1))) {
internal_tick = external_tick;
}
if (internal_tick <= external_tick) {
counter -= phase_mult(sync_interval);
} else {
if (counter > sync_interval) {
counter += phase_mult(counter - sync_interval);
}
}
// update internal clock base counter if (mode == EXTERNAL_CLOCK) {
float diff = 1/((float)counter/1000000.0); uint32_t u_timer = micros();
float bpm = (float)((float)(diff/24.0) * 60.0); sync_interval = clock_diff(external_clock, u_timer);
if (bpm != tempo) {
if (bpm > 1 && bpm < 300) { if (internal_tick <= external_tick) {
tempo = bpm; counter -= phase_mult(sync_interval);
setTimerTempo(tempo); } else {
} if (counter > sync_interval) {
counter += phase_mult(counter - sync_interval);
} }
} }
if (mod6_counter == 6) {
mod6_counter = 0;
}
//} else { // update internal clock timer frequency
// counter--; float bpm = freqToBpm(counter);
//} if (bpm != tempo) {
if (bpm >= MIN_BPM && bpm <= MAX_BPM) {
tempo = bpm;
setTimerTempo(tempo);
}
}
}
} }
// elapsed time support // elapsed time support

@ -39,6 +39,8 @@ namespace umodular { namespace clock {
#define PHASE_FACTOR 16 #define PHASE_FACTOR 16
#define EXT_INTERVAL_BUFFER_SIZE 24
#define SECS_PER_MIN (60UL) #define SECS_PER_MIN (60UL)
#define SECS_PER_HOUR (3600UL) #define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY (SECS_PER_HOUR * 24L) #define SECS_PER_DAY (SECS_PER_HOUR * 24L)
@ -53,6 +55,7 @@ class uClockClass {
private: private:
void setTimerTempo(float bpm); void setTimerTempo(float bpm);
float inline freqToBpm(uint32_t freq);
void (*onClock96PPQNCallback)(uint32_t * tick); void (*onClock96PPQNCallback)(uint32_t * tick);
void (*onClock32PPQNCallback)(uint32_t * tick); void (*onClock32PPQNCallback)(uint32_t * tick);
@ -60,16 +63,27 @@ class uClockClass {
void (*onClockStartCallback)(); void (*onClockStartCallback)();
void (*onClockStopCallback)(); void (*onClockStopCallback)();
volatile uint32_t internal_tick;
volatile uint32_t external_tick;
volatile uint32_t interval; volatile uint32_t interval;
volatile uint32_t external_clock; volatile uint32_t external_clock;
uint32_t tick_us_interval; uint32_t tick_us_interval;
float tick_hertz_interval; float tick_hertz_interval;
uint32_t div32th_counter;
uint32_t div16th_counter; volatile uint32_t internal_tick;
uint8_t mod6_counter; volatile uint32_t external_tick;
uint16_t counter;
// tick external and internal control
volatile uint32_t indiv32th_counter;
volatile uint32_t indiv16th_counter;
volatile uint8_t inmod6_counter;
volatile uint32_t div96th_counter;
volatile uint32_t div32th_counter;
volatile uint32_t div16th_counter;
volatile uint8_t mod6_counter;
uint32_t counter;
uint16_t pll_x; uint16_t pll_x;
uint32_t last_tick; uint32_t last_tick;
@ -80,6 +94,9 @@ class uClockClass {
uint16_t last_interval; uint16_t last_interval;
uint16_t sync_interval; uint16_t sync_interval;
uint16_t ext_interval_buffer[EXT_INTERVAL_BUFFER_SIZE];
uint16_t ext_interval_idx;
public: public:
enum { enum {

Loading…
Cancel
Save