added clock output callback for the following resolutions 1PPQN, 2PPQN, 4PPQN, 8PPQN, 12PPQN and 48PPQN

develop
midilab 6 days ago
parent 1a569e4cb1
commit e1d6674635
  1. 137
      src/uClock.cpp
  2. 57
      src/uClock.h

@ -126,7 +126,13 @@ uClockClass::uClockClass()
resetCounters();
onPPQNCallback = nullptr;
onSync1Callback = nullptr;
onSync2Callback = nullptr;
onSync4Callback = nullptr;
onSync8Callback = nullptr;
onSync12Callback = nullptr;
onSync24Callback = nullptr;
onSync48Callback = nullptr;
onStepCallback = nullptr;
onClockStartCallback = nullptr;
onClockStopCallback = nullptr;
@ -149,6 +155,11 @@ uint32_t uClockClass::bpmToMicroSeconds(float bpm)
void uClockClass::calculateReferencedata()
{
mod_clock_ref = ppqn / clock_ppqn;
mod_sync1_ref = ppqn / PPQN_1;
mod_sync2_ref = ppqn / PPQN_2;
mod_sync4_ref = ppqn / PPQN_4;
mod_sync8_ref = ppqn / PPQN_8;
mod_sync12_ref = ppqn / PPQN_12;
mod_sync24_ref = ppqn / PPQN_24;
mod_sync48_ref = ppqn / PPQN_48;
mod_step_ref = ppqn / 4;
@ -156,20 +167,18 @@ void uClockClass::calculateReferencedata()
void uClockClass::setPPQN(PPQNResolution resolution)
{
// stop clock to make it safe changing those references
// so we avoid volatile then and ATOMIC everywhere
//stop();
ppqn = resolution;
calculateReferencedata();
ATOMIC(
ppqn = resolution;
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();
ATOMIC(
clock_ppqn = resolution;
calculateReferencedata();
)
}
void uClockClass::start()
@ -284,14 +293,25 @@ void uClockClass::resetCounters()
int_clock_tick = 0;
mod_clock_counter = 0;
mod_step_counter = 0;
mod_sync24_counter = 0;
sync24_tick = 0;
mod_sync48_counter = 0;
sync48_tick = 0;
step_counter = 0;
ext_clock_tick = 0;
ext_clock_us = 0;
ext_interval_idx = 0;
// sync output counters
mod_sync1_counter = 0;
sync1_tick = 0;
mod_sync2_counter = 0;
sync2_tick = 0;
mod_sync4_counter = 0;
sync4_tick = 0;
mod_sync8_counter = 0;
sync8_tick = 0;
mod_sync12_counter = 0;
sync12_tick = 0;
mod_sync24_counter = 0;
sync24_tick = 0;
mod_sync48_counter = 0;
sync48_tick = 0;
for (uint8_t i=0; i < EXT_INTERVAL_BUFFER_SIZE; i++) {
ext_interval_buffer[i] = 0;
@ -426,7 +446,7 @@ void uClockClass::handleExternalClock()
void uClockClass::handleTimerInt()
{
// reset mod_clock_counter
// track main input clock counter
if (mod_clock_counter == mod_clock_ref)
mod_clock_counter = 0;
@ -467,56 +487,105 @@ void uClockClass::handleTimerInt()
// internal clock tick me!
++int_clock_tick;
}
++mod_clock_counter;
// Sync24 callback
if (mod_sync24_counter == mod_sync24_ref)
mod_sync24_counter = 0;
// ALL OUTPUT SYNC CALLBACKS
// Sync1 callback
if (onSync1Callback) {
if (mod_sync1_counter == mod_sync1_ref)
mod_sync1_counter = 0;
if (mod_sync1_counter == 0) {
onSync1Callback(sync1_tick);
++sync1_tick;
}
++mod_sync1_counter;
}
// Sync2 callback
if (onSync2Callback) {
if (mod_sync2_counter == mod_sync2_ref)
mod_sync2_counter = 0;
if (mod_sync2_counter == 0) {
onSync2Callback(sync2_tick);
++sync2_tick;
}
++mod_sync2_counter;
}
// Sync4 callback
if (onSync4Callback) {
if (mod_sync4_counter == mod_sync4_ref)
mod_sync4_counter = 0;
if (mod_sync4_counter == 0) {
onSync4Callback(sync4_tick);
++sync4_tick;
}
++mod_sync4_counter;
}
// Sync8 callback
if (onSync8Callback) {
if (mod_sync8_counter == mod_sync8_ref)
mod_sync8_counter = 0;
if (mod_sync8_counter == 0) {
onSync8Callback(sync8_tick);
++sync8_tick;
}
++mod_sync8_counter;
}
// Sync12 callback
if (onSync12Callback) {
if (mod_sync12_counter == mod_sync12_ref)
mod_sync12_counter = 0;
if (mod_sync12_counter == 0) {
onSync12Callback(sync12_tick);
++sync12_tick;
}
++mod_sync12_counter;
}
// Sync24 callback
if (onSync24Callback) {
if (mod_sync24_counter == mod_sync24_ref)
mod_sync24_counter = 0;
if (mod_sync24_counter == 0) {
onSync24Callback(sync24_tick);
++sync24_tick;
}
++mod_sync24_counter;
}
// Sync48 callback
if (mod_sync48_counter == mod_sync48_ref)
mod_sync48_counter = 0;
if (onSync48Callback) {
if (mod_sync48_counter == mod_sync48_ref)
mod_sync48_counter = 0;
if (mod_sync48_counter == 0) {
onSync48Callback(sync48_tick);
++sync48_tick;
}
++mod_sync48_counter;
}
// PPQNCallback time!
// main PPQNCallback
if (onPPQNCallback) {
onPPQNCallback(tick);
++tick;
}
// reset step mod counter reference ?
if (mod_step_counter == mod_step_ref)
mod_step_counter = 0;
// step callback to support 16th old school style sequencers
// with builtin shuffle for this callback only
if (onStepCallback) {
if (mod_step_counter == mod_step_ref)
mod_step_counter = 0;
// processShufle make use of mod_step_counter == 0 logic too
if (processShuffle()) {
onStepCallback(step_counter);
// going forward to the next step call
++step_counter;
}
++mod_step_counter;
}
// tick me!
++tick;
// increment mod counters
++mod_clock_counter;
++mod_sync24_counter;
++mod_sync48_counter;
++mod_step_counter;
}
// elapsed time support

@ -34,16 +34,6 @@
namespace umodular { namespace clock {
// for extended steps in memory style and make use of 96ppqn for record propurse we can
// keep array[step] memory layout and add new information about note possition to be check for the entire ppqn pulse
// example: for a whole 24 pulses we only check array[step].offset that can vary from 0 to 24(ppqn/4)
// time/tick notation and representation notes:
// one quarter note == 4 steps in 16th notes step sequencer style
// PPQN / 4 = pulses in between steps(from step sequencer perspective, a quarter note have 4 steps)
// 24 PPQN (6 pulses per step)
// 48 PPQN (12 pulses per step)
// 96 PPQN (24 pulses per step)
// min: -(ppqn/4)-1 step, max: (ppqn/4)-1 steps
// adjust the size of you template if more than 16 shuffle step info needed
#define MAX_SHUFFLE_TEMPLATE_SIZE 16
@ -108,12 +98,27 @@ class uClockClass {
void setOnStep(void (*callback)(uint32_t step)) {
onStepCallback = callback;
}
// multiple output clock signatures
void setOnSync1(void (*callback)(uint32_t tick)) {
onSync1Callback = callback;
}
// setOnSync1
// setOnSync2
// setOnSync4
// setOnSync8
// setOnSync12
void setOnSync2(void (*callback)(uint32_t tick)) {
onSync2Callback = callback;
}
void setOnSync4(void (*callback)(uint32_t tick)) {
onSync4Callback = callback;
}
void setOnSync8(void (*callback)(uint32_t tick)) {
onSync8Callback = callback;
}
void setOnSync12(void (*callback)(uint32_t tick)) {
onSync12Callback = callback;
}
void setOnSync24(void (*callback)(uint32_t tick)) {
onSync24Callback = callback;
@ -185,6 +190,11 @@ class uClockClass {
void (*onPPQNCallback)(uint32_t tick);
void (*onStepCallback)(uint32_t step);
void (*onSync1Callback)(uint32_t tick);
void (*onSync2Callback)(uint32_t tick);
void (*onSync4Callback)(uint32_t tick);
void (*onSync8Callback)(uint32_t tick);
void (*onSync12Callback)(uint32_t tick);
void (*onSync24Callback)(uint32_t tick);
void (*onSync48Callback)(uint32_t tick);
void (*onClockStartCallback)();
@ -201,6 +211,23 @@ class uClockClass {
uint8_t mod_step_counter;
uint8_t mod_step_ref;
uint32_t step_counter; // should we go uint16_t?
// clock output counters, ticks and references
uint8_t mod_sync1_counter;
uint8_t mod_sync1_ref;
uint32_t sync1_tick;
uint8_t mod_sync2_counter;
uint8_t mod_sync2_ref;
uint32_t sync2_tick;
uint8_t mod_sync4_counter;
uint8_t mod_sync4_ref;
uint32_t sync4_tick;
uint8_t mod_sync8_counter;
uint8_t mod_sync8_ref;
uint32_t sync8_tick;
uint8_t mod_sync12_counter;
uint8_t mod_sync12_ref;
uint32_t sync12_tick;
uint8_t mod_sync24_counter;
uint8_t mod_sync24_ref;
uint32_t sync24_tick;

Loading…
Cancel
Save