bool32 a
bool32 b
bool32.pulse up
bool32.pulse down
bool32.pulse step
objref controller object
int safe_a, prev_a, new_a;
int safe_b, prev_b, new_b;
int a_changed_count, a_same_count;
int b_changed_count, b_same_count;
int firstcount;
int count;
int prev_up, prev_down;
int accelerator;
safe_a = prev_a = 0;
safe_b = prev_b = 0;
firstcount = 2;
a_changed_count = a_same_count = 0;
b_changed_count = b_same_count = 0;
count = 0;
prev_up = 0;
prev_down = 0;
accelerator = 0;
outlet_up = outlet_down = 0;
#if 0
new_a = inlet_a>0;
new_b = inlet_b>0;
if (new_a ^ prev_a) {
a_changed_count++;
if (a_changed_count > attr_ctrl.debounce) safe_a = new_a;
} else {
a_changed_count = 0;
}
if (new_b ^ prev_b) {
b_changed_count++;
if (b_changed_count > attr_ctrl.debounce) safe_b = new_b;
} else {
b_changed_count = 0;
}
#else
// Majority filter, pick the majority of the latest debounce*2+1 samples
// Works better than the simple debouncer above
new_a = (new_a << 1) | inlet_a > 0; // shift inlet bits left
new_b = (new_b << 1) | inlet_b > 0;
safe_a = __builtin_popcount(new_a & attr_ctrl.filt_mask) >= attr_ctrl.debounce;
safe_b = __builtin_popcount(new_b & attr_ctrl.filt_mask) >= attr_ctrl.debounce;
#endif
if (safe_a ^ prev_a) {
// LogTextMessage("Diff a count %d", count);
if (!firstcount || !firstcount--) // skip first changes
if (!accelerator &&
count >= attr_ctrl.debounce) // only accept if not toggling too fast
if (attr_ctrl.rate || safe_a) // always if full or half
if (safe_a ^ safe_b)
outlet_down = 1;
else
outlet_up = 1;
prev_a = safe_a;
} else if (safe_b ^ prev_b) {
// LogTextMessage("Diff b count %d", count);
if (!accelerator && attr_ctrl.rate == 2 &&
count > 2 * attr_ctrl.debounce) // full only
if (!firstcount || !firstcount--) // skip first changes
if (safe_a ^ !safe_b)
outlet_down = 1;
else
outlet_up = 1;
prev_b = safe_b;
}
if (accelerator) {
outlet_up = prev_up;
outlet_down = prev_down;
accelerator--;
// LogTextMessage("Acc %d Up %d Down %d", accelerator, outlet_up,
// outlet_down);
} else if (outlet_up || outlet_down) {
// LogTextMessage("Up %d Down %d Count %d", outlet_up, outlet_down, count);
// If encoder turned fast enough, increase output by factor
if (count < attr_ctrl.thresh)
accelerator = attr_ctrl.factor;
// accelerator = attr_factor / (count ? count : 1); // accelerator = 10 if
// count = 15, etc
prev_up = outlet_up;
prev_down = outlet_down;
count = 0;
}
if (count < 3000) // avoid potential long-term wrap
count++;
outlet_step = outlet_down | outlet_up;