tests and tunning for external sync and phase_mult system

pull/5/head
midilab 2 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;
}
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) {
return new_clock - old_clock;
} else {
return new_clock + (65535 - old_clock);
return new_clock + (4294967295 - old_clock);
}
}
@ -207,8 +207,23 @@ void uClockClass::setTempo(float 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()
{
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;
}
@ -239,7 +254,11 @@ void uClockClass::resetCounters()
external_tick = 0;
div32th_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
@ -256,12 +275,6 @@ void uClockClass::shuffle()
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) {
case PAUSED:
@ -272,6 +285,34 @@ void uClockClass::handleExternalClock()
break;
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) {
interval = last_interval;
} else {
@ -283,68 +324,67 @@ void uClockClass::handleExternalClock()
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) {
onClock96PPQNCallback(&internal_tick);
if (mod6_counter == 0) {
if (onClock32PPQNCallback) {
onClock32PPQNCallback(&div32th_counter);
}
if (mod6_counter == 0) {
if (onClock32PPQNCallback) {
onClock32PPQNCallback(&div32th_counter);
}
if (onClock16PPQNCallback) {
onClock16PPQNCallback(&div16th_counter);
}
div16th_counter++;
div32th_counter++;
if (onClock16PPQNCallback) {
onClock16PPQNCallback(&div16th_counter);
}
div16th_counter++;
div32th_counter++;
}
if (mod6_counter == 3) {
if (onClock32PPQNCallback) {
onClock32PPQNCallback(&div32th_counter);
}
div32th_counter++;
if (mod6_counter == 3) {
if (onClock32PPQNCallback) {
onClock32PPQNCallback(&div32th_counter);
}
div32th_counter++;
}
// tick me!
internal_tick++;
mod6_counter++;
// tick me!
internal_tick++;
mod6_counter++;
if (mode == EXTERNAL_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;
}
if (internal_tick <= external_tick) {
counter -= phase_mult(sync_interval);
} else {
if (counter > sync_interval) {
counter += phase_mult(counter - sync_interval);
}
}
if (mod6_counter == 6) {
mod6_counter = 0;
}
// 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 (mode == EXTERNAL_CLOCK) {
uint32_t u_timer = micros();
sync_interval = clock_diff(external_clock, u_timer);
if (internal_tick <= external_tick) {
counter -= phase_mult(sync_interval);
} else {
if (counter > sync_interval) {
counter += phase_mult(counter - sync_interval);
}
}
if (mod6_counter == 6) {
mod6_counter = 0;
}
//} else {
// counter--;
//}
// update internal clock timer frequency
float bpm = freqToBpm(counter);
if (bpm != tempo) {
if (bpm >= MIN_BPM && bpm <= MAX_BPM) {
tempo = bpm;
setTimerTempo(tempo);
}
}
}
}
// elapsed time support

@ -39,6 +39,8 @@ 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)
@ -53,6 +55,7 @@ class uClockClass {
private:
void setTimerTempo(float bpm);
float inline freqToBpm(uint32_t freq);
void (*onClock96PPQNCallback)(uint32_t * tick);
void (*onClock32PPQNCallback)(uint32_t * tick);
@ -60,16 +63,27 @@ class uClockClass {
void (*onClockStartCallback)();
void (*onClockStopCallback)();
volatile uint32_t internal_tick;
volatile uint32_t external_tick;
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;
uint16_t counter;
volatile uint32_t internal_tick;
volatile uint32_t external_tick;
// 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;
uint32_t last_tick;
@ -80,6 +94,9 @@ class uClockClass {
uint16_t last_interval;
uint16_t sync_interval;
uint16_t ext_interval_buffer[EXT_INTERVAL_BUFFER_SIZE];
uint16_t ext_interval_idx;
public:
enum {

Loading…
Cancel
Save