Browse Source

Gates: Change EOG (End of gate) output to Delay. Implement gate delay algorithm.

tags/v2.3.0
Andrew Belt 2 years ago
parent
commit
002483eedf
1 changed files with 58 additions and 18 deletions
  1. +58
    -18
      src/Gates.cpp

+ 58
- 18
src/Gates.cpp View File

@@ -19,7 +19,7 @@ struct Gates : Module {
FLIP_OUTPUT,
FLOP_OUTPUT,
GATE_OUTPUT,
END_OUTPUT,
DELAY_OUTPUT,
OUTPUTS_LEN
};
enum LightId {
@@ -29,20 +29,32 @@ struct Gates : Module {
ENUMS(FLIP_LIGHT, 2),
ENUMS(FLOP_LIGHT, 2),
ENUMS(GATE_LIGHT, 2),
ENUMS(END_LIGHT, 2),
ENUMS(DELAY_LIGHT, 2),
LIGHTS_LEN
};

dsp::BooleanTrigger resetParamTrigger;
bool state[16] = {};
// Bit field for each channel
uint16_t stateBits = 0;
dsp::SchmittTrigger resetTrigger[16];
dsp::PulseGenerator risePulse[16];
dsp::PulseGenerator fallPulse[16];
dsp::PulseGenerator eogPulse[16];
bool flop[16] = {};
float gateTime[16] = {};
dsp::ClockDivider lightDivider;

double time = 0.0;
struct StateEvent {
double time;
uint16_t stateBits;

bool operator<(const StateEvent& other) const {
return time < other.time;
}
};
// TODO Change this to a circular buffer with binary search, to avoid allocations.
std::set<StateEvent> stateEvents;

Gates() {
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
configParam(LENGTH_PARAM, std::log2(1e-3f), std::log2(10.f), std::log2(0.1f), "Gate length", " ms", 2, 1000);
@@ -55,7 +67,7 @@ struct Gates : Module {
configOutput(FLIP_OUTPUT, "Flip");
configOutput(FLOP_OUTPUT, "Flop");
configOutput(GATE_OUTPUT, "Gate");
configOutput(END_OUTPUT, "End of gate");
configOutput(DELAY_OUTPUT, "Gate delay");

lightDivider.setDivision(32);
for (int c = 0; c < 16; c++) {
@@ -71,7 +83,7 @@ struct Gates : Module {
bool anyFlip = false;
bool anyFlop = false;
bool anyGate = false;
bool anyEnd = false;
bool anyDelay = false;

// Reset
bool resetButton = false;
@@ -79,26 +91,32 @@ struct Gates : Module {
resetButton = true;
}

bool newState = false;

// Process channels
for (int c = 0; c < channels; c++) {
float in = inputs[IN_INPUT].getVoltage(c);

if (state[c]) {
if (stateBits & (1 << c)) {
// HIGH to LOW
if (in <= 0.1f) {
state[c] = false;
// states[c] = false
stateBits &= ~(1 << c);
fallPulse[c].trigger(1e-3f);
newState = true;
}
}
else {
// LOW to HIGH
if (in >= 2.f) {
state[c] = true;
// states[c] = true
stateBits |= (1 << c);
risePulse[c].trigger(1e-3f);
// Flip flop
flop[c] ^= true;
// Gate
gateTime[c] = 0.f;
newState = true;
}
}

@@ -118,7 +136,6 @@ struct Gates : Module {
gateTime[c] += args.sampleTime;
if (reset || gateTime[c] >= gateLength) {
gateTime[c] = INFINITY;
eogPulse[c].trigger(1e-3f);
}
}

@@ -141,17 +158,40 @@ struct Gates : Module {
outputs[GATE_OUTPUT].setVoltage(gate ? 10.f : 0.f, c);
anyGate = anyGate || gate;

bool end = eogPulse[c].process(args.sampleTime);
outputs[END_OUTPUT].setVoltage(end ? 10.f : 0.f, c);
anyEnd = anyEnd || end;
// Gate delay output
bool delayGate = false;
// Timestamp of past gate
double delayTime = time - gateLength;
// Find event less than or equal to delayTime.
// If not found, gate will be off.
auto eventIt = stateEvents.upper_bound({delayTime, 0});
if (eventIt != stateEvents.begin()) {
eventIt--;
const StateEvent& event = *eventIt;
delayGate = event.stateBits & (1 << c);
}

outputs[DELAY_OUTPUT].setVoltage(delayGate ? 10.f : 0.f, c);
anyDelay = anyDelay || delayGate;
}

// Push state event
if (newState) {
// Keep buffer a reasonable size
if (stateEvents.size() >= (1 << 12) - 1) {
stateEvents.erase(stateEvents.begin());
}

stateEvents.insert({time, stateBits});
}
time += args.sampleTime;

outputs[RISE_OUTPUT].setChannels(channels);
outputs[FALL_OUTPUT].setChannels(channels);
outputs[FLIP_OUTPUT].setChannels(channels);
outputs[FLOP_OUTPUT].setChannels(channels);
outputs[GATE_OUTPUT].setChannels(channels);
outputs[END_OUTPUT].setChannels(channels);
outputs[DELAY_OUTPUT].setChannels(channels);

if (lightDivider.process()) {
float lightTime = args.sampleTime * lightDivider.getDivision();
@@ -166,8 +206,8 @@ struct Gates : Module {
lights[FLOP_LIGHT + 1].setBrightnessSmooth(anyFlop && channels > 1, lightTime);
lights[GATE_LIGHT + 0].setBrightnessSmooth(anyGate && channels <= 1, lightTime);
lights[GATE_LIGHT + 1].setBrightnessSmooth(anyGate && channels > 1, lightTime);
lights[END_LIGHT + 0].setBrightnessSmooth(anyEnd && channels <= 1, lightTime);
lights[END_LIGHT + 1].setBrightnessSmooth(anyEnd && channels > 1, lightTime);
lights[DELAY_LIGHT + 0].setBrightnessSmooth(anyDelay && channels <= 1, lightTime);
lights[DELAY_LIGHT + 1].setBrightnessSmooth(anyDelay && channels > 1, lightTime);
}
}
};
@@ -195,14 +235,14 @@ struct GatesWidget : ModuleWidget {
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.297, 97.958)), module, Gates::FLIP_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(18.134, 97.958)), module, Gates::FLOP_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.297, 113.115)), module, Gates::GATE_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(18.134, 113.115)), module, Gates::END_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(18.134, 113.115)), module, Gates::DELAY_OUTPUT));

addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(11.027, 79.007)), module, Gates::RISE_LIGHT));
addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(21.864, 79.007)), module, Gates::FALL_LIGHT));
addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(11.027, 94.233)), module, Gates::FLIP_LIGHT));
addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(21.864, 94.233)), module, Gates::FLOP_LIGHT));
addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(11.027, 109.393)), module, Gates::GATE_LIGHT));
addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(21.864, 109.393)), module, Gates::END_LIGHT));
addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(21.864, 109.393)), module, Gates::DELAY_LIGHT));
}
};



Loading…
Cancel
Save