initial slave sync new implementation setup, need some tests and tunnings...

pull/5/head
midilab 2 years ago
parent 635c42de41
commit 7174895426
  1. 94
      src/uClock.cpp
  2. 21
      src/uClock.h

@ -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) {

@ -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);

Loading…
Cancel
Save