commit 62a0883bd4946d4056e15eadb8892f996ddd4024
parent 538817a5f18b4ff81257da2b7c891372245f4548
Author: Matt Demanett <matt@demanett.net>
Date: Sun, 5 May 2019 00:39:05 -0400
8:1, 1:8, ADDR-SEQ: add "Select on clock" option: the effective select value only changes when a clock is received. #46
Diffstat:
7 files changed, 155 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
@@ -333,6 +333,8 @@ As a multiplexer, it routes an input to the output under control of the SELECT k
Both functions may be used simultaneously: the SELECT+CV value is added to the sequential/clocked value, wrapping around. Note that the STEPS value only affects the sequential value; for example, using a clock input and setting STEPS to 2 will yield an alternation between two adjacent inputs, but this pair can be selected with the SELECT knob or CV.
+On the context (right-click) menu, if option "Select on clock" is selected, then the select value (knob and CV) is checked and used to modify the active step only when a clock is received, rather than continuously.
+
#### 1:8
1:8 is the opposite of 8:1 -- it routes a single input to 1 of 8 outputs. The control circuit behavior (CLOCK, SELECT, etc) is the same.
diff --git a/src/AddrSeq.cpp b/src/AddrSeq.cpp
@@ -1,6 +1,8 @@
#include "AddrSeq.hpp"
+#define SELECT_ON_CLOCK "select_on_clock"
+
void AddrSeq::onReset() {
_step = 0;
_clock.reset();
@@ -11,6 +13,19 @@ void AddrSeq::onSampleRateChange() {
_timer.setParams(engineGetSampleRate(), 0.001f);
}
+json_t* AddrSeq::toJson() {
+ json_t* root = json_object();
+ json_object_set_new(root, SELECT_ON_CLOCK, json_boolean(_selectOnClock));
+ return root;
+}
+
+void AddrSeq::fromJson(json_t* root) {
+ json_t* s = json_object_get(root, SELECT_ON_CLOCK);
+ if (s) {
+ _selectOnClock = json_is_true(s);
+ }
+}
+
void AddrSeq::step() {
bool reset = _reset.process(inputs[RESET_INPUT].value);
if (reset) {
@@ -19,13 +34,17 @@ void AddrSeq::step() {
bool timer = _timer.next();
bool clock = _clock.process(inputs[CLOCK_INPUT].value) && !timer;
- int steps = clamp(params[STEPS_PARAM].value, 1.0f, 8.0f);
+ int steps = params[STEPS_PARAM].value;
int reverse = 1 - 2 * (params[DIRECTION_PARAM].value == 0.0f);
_step = (_step + reverse * clock) % steps;
_step += (_step < 0) * steps;
_step -= _step * reset;
- int step = _step + (int)params[SELECT_PARAM].value;
- step += (int)(clamp(inputs[SELECT_INPUT].value, 0.0f, 10.0f) * 0.1f * 8.0f);
+ int select = params[SELECT_PARAM].value;
+ select += clamp(inputs[SELECT_INPUT].value, 0.0f, 10.0f) * 0.1f * 8.0f;
+ if (!_selectOnClock || clock) {
+ _select = select;
+ }
+ int step = _step + _select;
step = step % 8;
float out = 0.0f;
@@ -36,6 +55,24 @@ void AddrSeq::step() {
outputs[OUT_OUTPUT].value = out * 10.0f;
}
+struct SelectOnClockMenuItem : MenuItem {
+ AddrSeq* _module;
+
+ SelectOnClockMenuItem(AddrSeq* module, const char* label)
+ : _module(module)
+ {
+ this->text = label;
+ }
+
+ void onAction(EventAction &e) override {
+ _module->_selectOnClock = !_module->_selectOnClock;
+ }
+
+ void step() override {
+ rightText = _module->_selectOnClock ? "✔" : "";
+ }
+};
+
struct AddrSeqWidget : ModuleWidget {
static constexpr int hp = 6;
@@ -116,6 +153,13 @@ struct AddrSeqWidget : ModuleWidget {
addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(out7LightPosition, module, AddrSeq::OUT7_LIGHT));
addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(out8LightPosition, module, AddrSeq::OUT8_LIGHT));
}
+
+ void appendContextMenu(Menu* menu) override {
+ AddrSeq* m = dynamic_cast<AddrSeq*>(module);
+ assert(m);
+ menu->addChild(new MenuLabel());
+ menu->addChild(new SelectOnClockMenuItem(m, "Select on clock"));
+ }
};
Model* modelAddrSeq = createModel<AddrSeq, AddrSeqWidget>("Bogaudio-AddrSeq", "ADDR-SEQ", "voltage-addressable sequencer", SEQUENCER_TAG);
diff --git a/src/AddrSeq.hpp b/src/AddrSeq.hpp
@@ -53,6 +53,8 @@ struct AddrSeq : Module {
Trigger _reset;
Timer _timer;
int _step;
+ bool _selectOnClock = false;
+ int _select = 0;
AddrSeq() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
onReset();
@@ -61,6 +63,8 @@ struct AddrSeq : Module {
void onReset() override;
void onSampleRateChange() override;
+ json_t* toJson() override;
+ void fromJson(json_t* root) override;
void step() override;
};
diff --git a/src/EightOne.cpp b/src/EightOne.cpp
@@ -1,6 +1,8 @@
#include "EightOne.hpp"
+#define SELECT_ON_CLOCK "select_on_clock"
+
void EightOne::onReset() {
_step = 0;
_clock.reset();
@@ -11,6 +13,19 @@ void EightOne::onSampleRateChange() {
_timer.setParams(engineGetSampleRate(), 0.001f);
}
+json_t* EightOne::toJson() {
+ json_t* root = json_object();
+ json_object_set_new(root, SELECT_ON_CLOCK, json_boolean(_selectOnClock));
+ return root;
+}
+
+void EightOne::fromJson(json_t* root) {
+ json_t* s = json_object_get(root, SELECT_ON_CLOCK);
+ if (s) {
+ _selectOnClock = json_is_true(s);
+ }
+}
+
void EightOne::step() {
bool reset = _reset.process(inputs[RESET_INPUT].value);
if (reset) {
@@ -19,13 +34,17 @@ void EightOne::step() {
bool timer = _timer.next();
bool clock = _clock.process(inputs[CLOCK_INPUT].value) && !timer;
- int steps = clamp(params[STEPS_PARAM].value, 1.0f, 8.0f);
+ int steps = params[STEPS_PARAM].value;
int reverse = 1 - 2 * (params[DIRECTION_PARAM].value == 0.0f);
_step = (_step + reverse * clock) % steps;
_step += (_step < 0) * steps;
_step -= _step * reset;
- int step = _step + (int)params[SELECT_PARAM].value;
- step += (int)(clamp(inputs[SELECT_INPUT].value, 0.0f, 10.0f) * 0.1f * 8.0f);
+ int select = params[SELECT_PARAM].value;
+ select += clamp(inputs[SELECT_INPUT].value, 0.0f, 10.0f) * 0.1f * 8.0f;
+ if (!_selectOnClock || clock) {
+ _select = select;
+ }
+ int step = _step + _select;
step = step % 8;
float out = 0.0f;
@@ -36,6 +55,24 @@ void EightOne::step() {
outputs[OUT_OUTPUT].value = out;
}
+struct SelectOnClockMenuItem : MenuItem {
+ EightOne* _module;
+
+ SelectOnClockMenuItem(EightOne* module, const char* label)
+ : _module(module)
+ {
+ this->text = label;
+ }
+
+ void onAction(EventAction &e) override {
+ _module->_selectOnClock = !_module->_selectOnClock;
+ }
+
+ void step() override {
+ rightText = _module->_selectOnClock ? "✔" : "";
+ }
+};
+
struct EightOneWidget : ModuleWidget {
static constexpr int hp = 6;
@@ -116,6 +153,13 @@ struct EightOneWidget : ModuleWidget {
addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(in7LightPosition, module, EightOne::IN7_LIGHT));
addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(in8LightPosition, module, EightOne::IN8_LIGHT));
}
+
+ void appendContextMenu(Menu* menu) override {
+ EightOne* m = dynamic_cast<EightOne*>(module);
+ assert(m);
+ menu->addChild(new MenuLabel());
+ menu->addChild(new SelectOnClockMenuItem(m, "Select on clock"));
+ }
};
Model* modelEightOne = createModel<EightOne, EightOneWidget>("Bogaudio-EightOne", "8:1", "demux & sequential switch", SWITCH_TAG);
diff --git a/src/EightOne.hpp b/src/EightOne.hpp
@@ -53,6 +53,8 @@ struct EightOne : Module {
Trigger _reset;
Timer _timer;
int _step;
+ bool _selectOnClock = false;
+ int _select = 0;
EightOne() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
onReset();
@@ -61,6 +63,8 @@ struct EightOne : Module {
void onReset() override;
void onSampleRateChange() override;
+ json_t* toJson() override;
+ void fromJson(json_t* root) override;
void step() override;
};
diff --git a/src/OneEight.cpp b/src/OneEight.cpp
@@ -1,6 +1,8 @@
#include "OneEight.hpp"
+#define SELECT_ON_CLOCK "select_on_clock"
+
void OneEight::onReset() {
_step = 0;
_clock.reset();
@@ -11,6 +13,19 @@ void OneEight::onSampleRateChange() {
_timer.setParams(engineGetSampleRate(), 0.001f);
}
+json_t* OneEight::toJson() {
+ json_t* root = json_object();
+ json_object_set_new(root, SELECT_ON_CLOCK, json_boolean(_selectOnClock));
+ return root;
+}
+
+void OneEight::fromJson(json_t* root) {
+ json_t* s = json_object_get(root, SELECT_ON_CLOCK);
+ if (s) {
+ _selectOnClock = json_is_true(s);
+ }
+}
+
void OneEight::step() {
bool reset = _reset.process(inputs[RESET_INPUT].value);
if (reset) {
@@ -19,13 +34,17 @@ void OneEight::step() {
bool timer = _timer.next();
bool clock = _clock.process(inputs[CLOCK_INPUT].value) && !timer;
- int steps = clamp(params[STEPS_PARAM].value, 1.0f, 8.0f);
+ int steps = params[STEPS_PARAM].value;
int reverse = 1 - 2 * (params[DIRECTION_PARAM].value == 0.0f);
_step = (_step + reverse * clock) % steps;
_step += (_step < 0) * steps;
_step -= _step * reset;
- int step = _step + (int)params[SELECT_PARAM].value;
- step += (int)(clamp(inputs[SELECT_INPUT].value, 0.0f, 10.0f) * 0.1f * 8.0f);
+ int select = params[SELECT_PARAM].value;
+ select += clamp(inputs[SELECT_INPUT].value, 0.0f, 10.0f) * 0.1f * 8.0f;
+ if (!_selectOnClock || clock) {
+ _select = select;
+ }
+ int step = _step + _select;
step = step % 8;
float in = inputs[IN_INPUT].value + !inputs[IN_INPUT].active * 10.0f;
@@ -35,6 +54,24 @@ void OneEight::step() {
}
}
+struct SelectOnClockMenuItem : MenuItem {
+ OneEight* _module;
+
+ SelectOnClockMenuItem(OneEight* module, const char* label)
+ : _module(module)
+ {
+ this->text = label;
+ }
+
+ void onAction(EventAction &e) override {
+ _module->_selectOnClock = !_module->_selectOnClock;
+ }
+
+ void step() override {
+ rightText = _module->_selectOnClock ? "✔" : "";
+ }
+};
+
struct OneEightWidget : ModuleWidget {
static constexpr int hp = 6;
@@ -115,6 +152,13 @@ struct OneEightWidget : ModuleWidget {
addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(out7LightPosition, module, OneEight::OUT7_LIGHT));
addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(out8LightPosition, module, OneEight::OUT8_LIGHT));
}
+
+ void appendContextMenu(Menu* menu) override {
+ OneEight* m = dynamic_cast<OneEight*>(module);
+ assert(m);
+ menu->addChild(new MenuLabel());
+ menu->addChild(new SelectOnClockMenuItem(m, "Select on clock"));
+ }
};
Model* modelOneEight = createModel<OneEight, OneEightWidget>("Bogaudio-OneEight", "1:8", "mux & sequential switch", SWITCH_TAG);
diff --git a/src/OneEight.hpp b/src/OneEight.hpp
@@ -53,6 +53,8 @@ struct OneEight : Module {
Trigger _reset;
Timer _timer;
int _step;
+ bool _selectOnClock = false;
+ int _select = 0;
OneEight() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
onReset();
@@ -61,6 +63,8 @@ struct OneEight : Module {
void onReset() override;
void onSampleRateChange() override;
+ json_t* toJson() override;
+ void fromJson(json_t* root) override;
void step() override;
};