|
|
@@ -32,18 +32,40 @@ struct Branches : Module { |
|
|
|
NUM_LIGHTS |
|
|
|
}; |
|
|
|
|
|
|
|
SchmittTrigger gateTrigger[2]; |
|
|
|
SchmittTrigger modeTrigger[2]; |
|
|
|
bool mode[2] = {}; |
|
|
|
bool outcome[2] = {}; |
|
|
|
SchmittTrigger gateTriggers[2]; |
|
|
|
SchmittTrigger modeTriggers[2]; |
|
|
|
bool modes[2] = {}; |
|
|
|
bool outcomes[2] = {}; |
|
|
|
|
|
|
|
Branches() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} |
|
|
|
|
|
|
|
json_t *toJson() override { |
|
|
|
json_t *rootJ = json_object(); |
|
|
|
json_t *modesJ = json_array(); |
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
|
json_array_insert_new(modesJ, i, json_boolean(modes[i])); |
|
|
|
} |
|
|
|
json_object_set_new(rootJ, "modes", modesJ); |
|
|
|
return rootJ; |
|
|
|
} |
|
|
|
|
|
|
|
void fromJson(json_t *rootJ) override { |
|
|
|
json_t *modesJ = json_object_get(rootJ, "modes"); |
|
|
|
if (modesJ) { |
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
|
json_t *modeJ = json_array_get(modesJ, i); |
|
|
|
if (modeJ) |
|
|
|
modes[i] = json_boolean_value(modeJ); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void step() override; |
|
|
|
|
|
|
|
void onReset() override { |
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
|
mode[i] = false; |
|
|
|
outcome[i] = false; |
|
|
|
modes[i] = false; |
|
|
|
outcomes[i] = false; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
@@ -53,27 +75,27 @@ void Branches::step() { |
|
|
|
float gate = 0.0; |
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
|
// mode button |
|
|
|
if (modeTrigger[i].process(params[MODE1_PARAM + i].value)) |
|
|
|
mode[i] = !mode[i]; |
|
|
|
if (modeTriggers[i].process(params[MODE1_PARAM + i].value)) |
|
|
|
modes[i] = !modes[i]; |
|
|
|
|
|
|
|
if (inputs[IN1_INPUT + i].active) |
|
|
|
gate = inputs[IN1_INPUT + i].value; |
|
|
|
|
|
|
|
if (gateTrigger[i].process(gate)) { |
|
|
|
if (gateTriggers[i].process(gate)) { |
|
|
|
// trigger |
|
|
|
float r = randomUniform(); |
|
|
|
float threshold = clamp(params[THRESHOLD1_PARAM + i].value + inputs[P1_INPUT + i].value / 10.f, 0.f, 1.f); |
|
|
|
bool toss = (r < threshold); |
|
|
|
if (!mode[i]) { |
|
|
|
// direct mode |
|
|
|
outcome[i] = toss; |
|
|
|
if (!modes[i]) { |
|
|
|
// direct modes |
|
|
|
outcomes[i] = toss; |
|
|
|
} |
|
|
|
else { |
|
|
|
// toggle mode |
|
|
|
outcome[i] = (outcome[i] != toss); |
|
|
|
// toggle modes |
|
|
|
outcomes[i] = (outcomes[i] != toss); |
|
|
|
} |
|
|
|
|
|
|
|
if (!outcome[i]) |
|
|
|
if (!outcomes[i]) |
|
|
|
lights[STATE1_POS_LIGHT + 2*i].value = 1.0; |
|
|
|
else |
|
|
|
lights[STATE1_NEG_LIGHT + 2*i].value = 1.0; |
|
|
@@ -81,10 +103,10 @@ void Branches::step() { |
|
|
|
|
|
|
|
lights[STATE1_POS_LIGHT + 2*i].value *= 1.0 - engineGetSampleTime() * 15.0; |
|
|
|
lights[STATE1_NEG_LIGHT + 2*i].value *= 1.0 - engineGetSampleTime() * 15.0; |
|
|
|
lights[MODE1_LIGHT + i].value = mode[i] ? 1.0 : 0.0; |
|
|
|
lights[MODE1_LIGHT + i].value = modes[i] ? 1.0 : 0.0; |
|
|
|
|
|
|
|
outputs[OUT1A_OUTPUT + i].value = outcome[i] ? 0.0 : gate; |
|
|
|
outputs[OUT1B_OUTPUT + i].value = outcome[i] ? gate : 0.0; |
|
|
|
outputs[OUT1A_OUTPUT + i].value = outcomes[i] ? 0.0 : gate; |
|
|
|
outputs[OUT1B_OUTPUT + i].value = outcomes[i] ? gate : 0.0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -122,10 +144,10 @@ struct BranchesWidget : ModuleWidget { |
|
|
|
Branches *branches; |
|
|
|
int channel; |
|
|
|
void onAction(EventAction &e) override { |
|
|
|
branches->mode[channel] ^= 1; |
|
|
|
branches->modes[channel] ^= 1; |
|
|
|
} |
|
|
|
void step() override { |
|
|
|
rightText = branches->mode[channel] ? "Toggle" : "Latch"; |
|
|
|
rightText = branches->modes[channel] ? "Toggle" : "Latch"; |
|
|
|
MenuItem::step(); |
|
|
|
} |
|
|
|
}; |
|
|
@@ -133,8 +155,8 @@ struct BranchesWidget : ModuleWidget { |
|
|
|
menu->addChild(construct<MenuLabel>()); |
|
|
|
|
|
|
|
menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Channels")); |
|
|
|
menu->addChild(construct<BranchesModeItem>(&MenuItem::text, "Channel 1 mode", &BranchesModeItem::branches, branches, &BranchesModeItem::channel, 0)); |
|
|
|
menu->addChild(construct<BranchesModeItem>(&MenuItem::text, "Channel 2 mode", &BranchesModeItem::branches, branches, &BranchesModeItem::channel, 1)); |
|
|
|
menu->addChild(construct<BranchesModeItem>(&MenuItem::text, "Channel 1 modes", &BranchesModeItem::branches, branches, &BranchesModeItem::channel, 0)); |
|
|
|
menu->addChild(construct<BranchesModeItem>(&MenuItem::text, "Channel 2 modes", &BranchesModeItem::branches, branches, &BranchesModeItem::channel, 1)); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|