diff --git a/Makefile b/Makefile
index 9a5e9ff..0aa4dcd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
SLUG = Fundamental
-VERSION = 0.5.0
+VERSION = 0.5.1
SOURCES = $(wildcard src/*.cpp)
diff --git a/res/SequentialSwitch1.svg b/res/SequentialSwitch1.svg
new file mode 100644
index 0000000..1df9f53
--- /dev/null
+++ b/res/SequentialSwitch1.svg
@@ -0,0 +1,484 @@
+
+
+
+
diff --git a/res/SequentialSwitch2.svg b/res/SequentialSwitch2.svg
new file mode 100644
index 0000000..30b87ed
--- /dev/null
+++ b/res/SequentialSwitch2.svg
@@ -0,0 +1,490 @@
+
+
+
+
diff --git a/src/Fundamental.cpp b/src/Fundamental.cpp
index 7bba3b7..303abbf 100644
--- a/src/Fundamental.cpp
+++ b/src/Fundamental.cpp
@@ -25,4 +25,6 @@ void init(rack::Plugin *p) {
p->addModel(createModel("Fundamental", "Mutes", "Mutes", SWITCH_TAG));
p->addModel(createModel("Fundamental", "Scope", "Scope", VISUAL_TAG));
p->addModel(createModel("Fundamental", "SEQ3", "SEQ-3", SEQUENCER_TAG));
+ p->addModel(createModel("Fundamental", "SequentialSwitch1", "Sequential Switch 1", UTILITY_TAG));
+ p->addModel(createModel("Fundamental", "SequentialSwitch2", "Sequential Switch 2", UTILITY_TAG));
}
diff --git a/src/Fundamental.hpp b/src/Fundamental.hpp
index 4f85f83..014ad74 100644
--- a/src/Fundamental.hpp
+++ b/src/Fundamental.hpp
@@ -67,3 +67,11 @@ struct SEQ3Widget : ModuleWidget {
SEQ3Widget();
Menu *createContextMenu() override;
};
+
+struct SequentialSwitch1Widget : ModuleWidget {
+ SequentialSwitch1Widget();
+};
+
+struct SequentialSwitch2Widget : ModuleWidget {
+ SequentialSwitch2Widget();
+};
diff --git a/src/SequentialSwitch.cpp b/src/SequentialSwitch.cpp
new file mode 100644
index 0000000..ee337d0
--- /dev/null
+++ b/src/SequentialSwitch.cpp
@@ -0,0 +1,131 @@
+#include "Fundamental.hpp"
+#include "dsp/digital.hpp"
+#include "dsp/filter.hpp"
+
+
+template
+struct SequentialSwitch : Module {
+ enum ParamIds {
+ CHANNELS_PARAM,
+ NUM_PARAMS
+ };
+ enum InputIds {
+ CLOCK_INPUT,
+ RESET_INPUT,
+ ENUMS(IN_INPUT, TYPE == 1 ? 1 : 4),
+ NUM_INPUTS
+ };
+ enum OutputIds {
+ ENUMS(OUT_OUTPUT, TYPE == 1 ? 4 : 1),
+ NUM_OUTPUTS
+ };
+ enum LightIds {
+ ENUMS(CHANNEL_LIGHT, 4),
+ NUM_LIGHTS
+ };
+
+ SchmittTrigger clockTrigger;
+ SchmittTrigger resetTrigger;
+ int channel = 0;
+ SlewLimiter channelFilter[4];
+
+ SequentialSwitch() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
+ clockTrigger.setThresholds(0.0, 2.0);
+ resetTrigger.setThresholds(0.0, 2.0);
+ for (int i = 0; i < 4; i++) {
+ channelFilter[i].rise = 0.01;
+ channelFilter[i].fall = 0.01;
+ }
+ }
+
+ void step() override {
+ // Determine current channel
+ if (clockTrigger.process(inputs[CLOCK_INPUT].value)) {
+ channel++;
+ }
+ if (resetTrigger.process(inputs[RESET_INPUT].value)) {
+ channel = 0;
+ }
+ int channels = 4 - (int) params[CHANNELS_PARAM].value;
+ channel %= channels;
+
+ // Filter channels
+ for (int i = 0; i < 4; i++) {
+ channelFilter[i].process(channel == i ? 1.0 : 0.0);
+ }
+
+ // Set outputs
+ if (TYPE == 1) {
+ float out = inputs[IN_INPUT + 0].value;
+ for (int i = 0; i < 4; i++) {
+ outputs[OUT_OUTPUT + i].value = channelFilter[i].out * out;
+ }
+ }
+ else {
+ float out = 0.0;
+ for (int i = 0; i < 4; i++) {
+ out += channelFilter[i].out * inputs[IN_INPUT + i].value;
+ }
+ outputs[OUT_OUTPUT + 0].value = out;
+ }
+
+ // Set lights
+ for (int i = 0; i < 4; i++) {
+ lights[CHANNEL_LIGHT + i].setBrightness(channelFilter[i].out);
+ }
+ }
+};
+
+
+SequentialSwitch1Widget::SequentialSwitch1Widget() {
+ typedef SequentialSwitch<1> TSequentialSwitch;
+ TSequentialSwitch *module = new TSequentialSwitch();
+ setModule(module);
+ setPanel(SVG::load(assetPlugin(plugin, "res/SequentialSwitch1.svg")));
+
+ addChild(createScrew(Vec(RACK_GRID_WIDTH, 0)));
+ addChild(createScrew(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+
+ addParam(createParam(mm2px(Vec(5.24619, 46.9153)), module, TSequentialSwitch::CHANNELS_PARAM, 0.0, 2.0, 0.0));
+
+ addInput(createInput(mm2px(Vec(3.51398, 17.694)), module, TSequentialSwitch::CLOCK_INPUT));
+ addInput(createInput(mm2px(Vec(3.51398, 32.1896)), module, TSequentialSwitch::RESET_INPUT));
+ addInput(createInput(mm2px(Vec(3.51536, 62.8096)), module, TSequentialSwitch::IN_INPUT + 0));
+
+ addOutput(createOutput(mm2px(Vec(3.51536, 77.8095)), module, TSequentialSwitch::OUT_OUTPUT + 0));
+ addOutput(createOutput(mm2px(Vec(3.51398, 87.8113)), module, TSequentialSwitch::OUT_OUTPUT + 1));
+ addOutput(createOutput(mm2px(Vec(3.51398, 97.809)), module, TSequentialSwitch::OUT_OUTPUT + 2));
+ addOutput(createOutput(mm2px(Vec(3.51398, 107.809)), module, TSequentialSwitch::OUT_OUTPUT + 3));
+
+ addChild(createLight>(mm2px(Vec(10.8203, 77.7158)), module, TSequentialSwitch::CHANNEL_LIGHT + 0));
+ addChild(createLight>(mm2px(Vec(10.8203, 87.7163)), module, TSequentialSwitch::CHANNEL_LIGHT + 1));
+ addChild(createLight>(mm2px(Vec(10.8203, 97.7167)), module, TSequentialSwitch::CHANNEL_LIGHT + 2));
+ addChild(createLight>(mm2px(Vec(10.8203, 107.716)), module, TSequentialSwitch::CHANNEL_LIGHT + 3));
+}
+
+
+SequentialSwitch2Widget::SequentialSwitch2Widget() {
+ typedef SequentialSwitch<2> TSequentialSwitch;
+ TSequentialSwitch *module = new TSequentialSwitch();
+ setModule(module);
+ setPanel(SVG::load(assetPlugin(plugin, "res/SequentialSwitch2.svg")));
+
+ addChild(createScrew(Vec(RACK_GRID_WIDTH, 0)));
+ addChild(createScrew(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+
+ addParam(createParam(mm2px(Vec(5.24619, 46.9153)), module, TSequentialSwitch::CHANNELS_PARAM, 0.0, 2.0, 0.0));
+
+ addInput(createInput(mm2px(Vec(3.51398, 17.694)), module, TSequentialSwitch::CLOCK_INPUT));
+ addInput(createInput(mm2px(Vec(3.51398, 32.191)), module, TSequentialSwitch::RESET_INPUT));
+ addInput(createInput(mm2px(Vec(3.51398, 62.811)), module, TSequentialSwitch::IN_INPUT + 0));
+ addInput(createInput(mm2px(Vec(3.51398, 72.8114)), module, TSequentialSwitch::IN_INPUT + 1));
+ addInput(createInput(mm2px(Vec(3.51398, 82.8091)), module, TSequentialSwitch::IN_INPUT + 2));
+ addInput(createInput(mm2px(Vec(3.51398, 92.8109)), module, TSequentialSwitch::IN_INPUT + 3));
+
+ addOutput(createOutput(mm2px(Vec(3.51398, 107.622)), module, TSequentialSwitch::OUT_OUTPUT + 0));
+
+ addChild(createLight>(mm2px(Vec(10.7321, 62.6277)), module, TSequentialSwitch::CHANNEL_LIGHT + 0));
+ addChild(createLight>(mm2px(Vec(10.7321, 72.6281)), module, TSequentialSwitch::CHANNEL_LIGHT + 1));
+ addChild(createLight>(mm2px(Vec(10.7321, 82.6285)), module, TSequentialSwitch::CHANNEL_LIGHT + 2));
+ addChild(createLight>(mm2px(Vec(10.7321, 92.6276)), module, TSequentialSwitch::CHANNEL_LIGHT + 3));
+}