diff --git a/Makefile b/Makefile index 4a0d6fe..2c320e1 100755 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ RACK_DIR ?= ../.. SLUG = AS -VERSION = 0.6.8 +VERSION = 0.6.9 FLAGS += SOURCES += $(wildcard src/*.cpp freeverb/*.cpp) diff --git a/res/Flow.svg b/res/Flow.svg index 9649656..c0d817b 100644 --- a/res/Flow.svg +++ b/res/Flow.svg @@ -37,11 +37,11 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1.7258659" - inkscape:cx="-41.48078" - inkscape:cy="234.09555" + inkscape:zoom="6.2307619" + inkscape:cx="59.390478" + inkscape:cy="341.3318" inkscape:document-units="mm" - inkscape:current-layer="layer3" + inkscape:current-layer="g961" showgrid="false" fit-margin-top="0" fit-margin-left="0" @@ -49,8 +49,8 @@ fit-margin-bottom="0" inkscape:window-width="1678" inkscape:window-height="1334" - inkscape:window-x="124" - inkscape:window-y="13" + inkscape:window-x="268" + inkscape:window-y="0" inkscape:window-maximized="0" units="px" /> + transform="matrix(0.26458333,0,0,0.26458333,-293.56898,-296.47329)"> + + + + + + + + + + + + + + + + + image/svg+xml + + SnH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SnH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/TriggersMKIII.svg b/res/TriggersMKIII.svg new file mode 100644 index 0000000..e40d653 --- /dev/null +++ b/res/TriggersMKIII.svg @@ -0,0 +1,368 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AS.cpp b/src/AS.cpp index 934373b..a8dcf91 100755 --- a/src/AS.cpp +++ b/src/AS.cpp @@ -31,9 +31,10 @@ void init(rack::Plugin *p) { p->addModel(modelMerge2_5); p->addModel(modelTriggersMKI); p->addModel(modelTriggersMKII); + p->addModel(modelTriggersMKIII); p->addModel(modelBPMCalc); p->addModel(modelCv2T); - + p->addModel(modelReScale); //EFFECTS p->addModel(modelDelayPlusFx); diff --git a/src/AS.hpp b/src/AS.hpp index 8323d16..ab03c09 100755 --- a/src/AS.hpp +++ b/src/AS.hpp @@ -29,12 +29,14 @@ extern Model *modelMerge2_5; extern Model *modelSteps; extern Model *modelTriggersMKI; extern Model *modelTriggersMKII; +extern Model *modelTriggersMKIII; extern Model *modelLaunchGate; extern Model *modelKillGate; extern Model *modelFlow; extern Model *modelSignalDelay; extern Model *modelBPMCalc; extern Model *modelCv2T; +extern Model *modelReScale; extern Model *modelDelayPlusFx; extern Model *modelDelayPlusStereoFx; @@ -81,6 +83,24 @@ struct as_KnobBlack : SVGKnob { } }; +struct as_KnobBlackSnap : as_KnobBlack { + as_KnobBlackSnap() { + snap = true; + } +}; + +struct as_KnobBlackSnap4 : as_KnobBlack { + as_KnobBlackSnap4() { + minAngle = -0.30 * M_PI; + maxAngle = 0.30 * M_PI; + snap = true; + } +}; + + + + + struct as_FxKnobWhite : SVGKnob { as_FxKnobWhite() { minAngle = -0.83 * M_PI; diff --git a/src/BPMClock.cpp b/src/BPMClock.cpp index e41c7c7..5ff59b9 100755 --- a/src/BPMClock.cpp +++ b/src/BPMClock.cpp @@ -107,6 +107,7 @@ struct BPMClock : Module { float tempo =120.0f; int time_sig_top, time_sig_bottom = 0; + int time_sig_bottom_old = 0; float frequency = 2.0f; int quarters_count_limit = 4; int eighths_count_limit = 2; @@ -160,6 +161,7 @@ void BPMClock::step() { time_sig_top = std::round(params[TIMESIGTOP_PARAM].value); time_sig_bottom = std::round(params[TIMESIGBOTTOM_PARAM].value); time_sig_bottom = std::pow(2,time_sig_bottom+1); + frequency = tempo/60.0f; @@ -192,15 +194,17 @@ void BPMClock::step() { }else{ if (time_sig_top == time_sig_bottom){ - clock.setFreq(frequency*4); quarters_count_limit = 4; eighths_count_limit = 2; - bars_count_limit = 16; + bars_count_limit = 16; + clock.setFreq(frequency*4); }else{ + //clock divisions if(time_sig_bottom == 4){ + //debug("time sig bottom = %i", time_sig_bottom); quarters_count_limit = 4; eighths_count_limit = 2; - bars_count_limit = time_sig_top * 4; + bars_count_limit = time_sig_top * 4; clock.setFreq(frequency*4); } if(time_sig_bottom == 8){ diff --git a/src/Flow.cpp b/src/Flow.cpp index 36e1bf8..b9250f7 100755 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -9,6 +9,7 @@ struct Flow: Module { enum ParamIds { SWITCH_1, SWITCH_2, + MODE_PARAM, NUM_PARAMS }; enum InputIds { @@ -40,6 +41,7 @@ struct Flow: Module { bool on_1 = false; bool on_2 = false; + bool light_inverted = false; float mute_fade1 =0.0f; float mute_fade2 =0.0f; @@ -79,6 +81,14 @@ struct Flow: Module { void Flow::step() { + if (params[MODE_PARAM].value){ + //switch lights turn on when the switch is enabled + light_inverted = false; + }else{ + //switch lights turn off when the switch is enabled + light_inverted = true; + } + //TRIGGER 1 if (btnTrigger1.process(params[SWITCH_1].value)||extTrigger1.process(inputs[CV_TRIG_INPUT_1].value)) { on_1 = !on_1; @@ -94,7 +104,12 @@ void Flow::step() { mute_fade1 = 1.0f; } outputs[OUTPUT_1].value = inputs[INPUT_1].value * mute_fade1; - lights[TRIGGER_LED_1].value = on_1 ? 1.0f : 0.0f; + if(light_inverted){ + lights[TRIGGER_LED_1].value = on_1 ? 0.0f : 1.0f; + }else{ + lights[TRIGGER_LED_1].value = on_1 ? 1.0f : 0.0f; + } + //TRIGGER 2 if (btnTrigger2.process(params[SWITCH_2].value)||extTrigger2.process(inputs[CV_TRIG_INPUT_2].value)) { on_2 = !on_2; @@ -110,7 +125,12 @@ void Flow::step() { mute_fade2 = 1.0f; } outputs[OUTPUT_2].value = inputs[INPUT_2].value * mute_fade2; - lights[TRIGGER_LED_2].value = on_2 ? 1.0f : 0.0f; + if(light_inverted){ + lights[TRIGGER_LED_2].value = on_2 ? 0.0f : 1.0f; + }else{ + lights[TRIGGER_LED_2].value = on_2 ? 1.0f : 0.0f; + } + } //////////////////////////////////// @@ -129,6 +149,9 @@ FlowWidget::FlowWidget(Flow *module) : ModuleWidget(module) { addChild(Widget::create(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + //OLD/NEW SWITCH FROM 40-250 TO 30-300 + addParam(ParamWidget::create(Vec(67, 23), module, Flow::MODE_PARAM, 0.0f, 1.0f, 1.0f)); + static const float led_offset = 3.3; static const float led_center = 15; static const float y_offset = 150; diff --git a/src/Phaser.cpp b/src/Phaser.cpp index 8ca6b1e..a5e15e6 100644 --- a/src/Phaser.cpp +++ b/src/Phaser.cpp @@ -120,8 +120,7 @@ class Phaser{ float Update( float inSamp ){ //calculate and update phaser sweep lfo... - float d = _dmin + (_dmax-_dmin) * ((sin( _lfoPhase ) + -1.f)/2.f); + float d = _dmin + (_dmax-_dmin) * ((sin( _lfoPhase ) + 1.f)/2.f); _lfoPhase += _lfoInc; if( _lfoPhase >= F_PI * 2.0f ) _lfoPhase -= F_PI * 2.0f; diff --git a/src/ReScale.cpp b/src/ReScale.cpp new file mode 100644 index 0000000..4d4ff78 --- /dev/null +++ b/src/ReScale.cpp @@ -0,0 +1,134 @@ +//************************************************************************************** +//Volt rescale module module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS +// +//************************************************************************************** +#include "AS.hpp" + +struct ReScale: Module { + enum ParamIds { + CONVERT_PARAM, + NUM_PARAMS + }; + enum InputIds { + INPUT_0, + INPUT_1, + INPUT_2, + INPUT_3, + NUM_INPUTS + }; + enum OutputIds { + OUTPUT, + NUM_OUTPUTS + }; + enum LightIds { + NUM_LIGHTS + }; + + int selection = 0; + float rescaled_value = 0.0f; + float input_value = 0.0f; + + float getNoteInVolts(float noteValue) { + int octaveInVolts = int(floorf(noteValue)); + float voltMinusOct = noteValue - octaveInVolts; + return voltMinusOct; + } + + ReScale() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + + } + void step() override; + +}; + +void ReScale::step() { + + selection = params[CONVERT_PARAM].value; + + if(inputs[INPUT_0].active){ + + input_value = clamp(inputs[INPUT_0].value, -5.0f,5.0f); + if(selection==0){ + rescaled_value = input_value; + }else if(selection==1){ + rescaled_value = rescale(input_value, -5.0f, 5.0f, 0.0f, 5.0f); + }else if(selection==2){ + rescaled_value = rescale(input_value, -5.0f, 5.0f, -10.0f, 10.0f); + }else if(selection==3){ + rescaled_value = rescale(input_value, -5.0f, 5.0f, 0.0f, 10.0f); + } + + }else if(inputs[INPUT_1].active){ + + input_value = clamp(inputs[INPUT_1].value, 0.0f, 5.0f); + if(selection==0){ + rescaled_value = rescale(input_value, 0.0f, 5.0f, -5.0f, 5.0f); + }else if(selection==1){ + rescaled_value = input_value; + }else if(selection==2){ + rescaled_value = rescale(input_value, 0.0f, 5.0f, -10.0f, 10.0f); + }else if(selection==3){ + rescaled_value = rescale(input_value, -5.0f, 5.0f, 0.0f, 10.0f); + } + + }else if(inputs[INPUT_2].active){ + + input_value = clamp(inputs[INPUT_2].value, 0.0f, 10.0f); + if(selection==0){ + rescaled_value = rescale(input_value, 0.0f, 10.0f, -5.0f, 5.0f); + }else if(selection==1){ + rescaled_value = rescale(input_value, 0.0f, 10.0f, 0.0f, 5.0f); + }else if(selection==2){ + rescaled_value = rescale(input_value, 0.0f, 10.0f, -10.0f, 10.0f); + }else if(selection==3){ + rescaled_value = input_value; + } + + }else if(inputs[INPUT_3].active){ + + input_value = inputs[INPUT_3].value; + if(selection==0){ + rescaled_value = input_value; + }else if(selection==1){ + rescaled_value = input_value; + }else if(selection==2){ + rescaled_value = input_value; + }else if(selection==3){ + //take the input of a midi KB, get the voltage minus octave, convert it to 1V/KEY + float ext_key = getNoteInVolts(input_value); + rescaled_value = clamp( rescale( ext_key, 0.0f, 1.0f, 0.0f, 11.0f ), 0.0f, 10.0f ); + } + + } + outputs[OUTPUT].value = rescaled_value; + +} + +//////////////////////////////////// +struct ReScaleWidget : ModuleWidget +{ + ReScaleWidget(ReScale *module); +}; + +ReScaleWidget::ReScaleWidget(ReScale *module) : ModuleWidget(module) { + + setPanel(SVG::load(assetPlugin(plugin, "res/ReScale.svg"))); + + //SCREWS - SPECIAL SPACING FOR RACK WIDTH*4 + addChild(Widget::create(Vec(0, 0))); + addChild(Widget::create(Vec(box.size.x - RACK_GRID_WIDTH, 0))); + addChild(Widget::create(Vec(0, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + addChild(Widget::create(Vec(box.size.x - RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + //PORTS + addInput(Port::create(Vec(18, 65), Port::INPUT, module, ReScale::INPUT_0)); + addInput(Port::create(Vec(18, 105), Port::INPUT, module, ReScale::INPUT_1)); + addInput(Port::create(Vec(18, 145), Port::INPUT, module, ReScale::INPUT_2)); + addInput(Port::create(Vec(18, 185), Port::INPUT, module, ReScale::INPUT_3)); + + addParam(ParamWidget::create(Vec(12, 230), module, ReScale::CONVERT_PARAM, 0.0f, 3.0f, 0.0f)); + + addOutput(Port::create(Vec(18, 280), Port::OUTPUT, module, ReScale::OUTPUT)); + + +} +Model *modelReScale = Model::create("AS", "ReScale", "Voltage Converter", UTILITY_TAG); \ No newline at end of file diff --git a/src/SignalDelay.cpp b/src/SignalDelay.cpp index 396e059..9f8727c 100755 --- a/src/SignalDelay.cpp +++ b/src/SignalDelay.cpp @@ -220,7 +220,7 @@ SignalDelayWidget::SignalDelayWidget(SignalDelay *module) : ModuleWidget(module) addChild(Widget::create(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); //KNOBS - addParam(ParamWidget::create(Vec(47, 80), module, SignalDelay::TIME_1_PARAM, 0.001f, 10.0f, 0.350f)); + addParam(ParamWidget::create(Vec(47, 80), module, SignalDelay::TIME_1_PARAM, 0.0f, 10.0f, 0.350f)); //CV INPUT addInput(Port::create(Vec(posX[0]+5, 87), Port::INPUT, module, SignalDelay::TIME_1_INPUT)); //INPUT @@ -238,7 +238,7 @@ SignalDelayWidget::SignalDelayWidget(SignalDelay *module) : ModuleWidget(module) display2->value = &module->lcd_tempo2; addChild(display2); //KNOBS - addParam(ParamWidget::create(Vec(47, 80+mod_offset), module, SignalDelay::TIME_2_PARAM, 0.001f, 10.0f, 0.350f)); + addParam(ParamWidget::create(Vec(47, 80+mod_offset), module, SignalDelay::TIME_2_PARAM, 0.0f, 10.0f, 0.350f)); //CV INPUT addInput(Port::create(Vec(posX[0]+5, 87+mod_offset), Port::INPUT, module, SignalDelay::TIME_2_INPUT)); //INPUT diff --git a/src/TriggersMKIII.cpp b/src/TriggersMKIII.cpp new file mode 100755 index 0000000..7a05c7a --- /dev/null +++ b/src/TriggersMKIII.cpp @@ -0,0 +1,210 @@ +//************************************************************************************** +//TriggersMKIII module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS +// +//************************************************************************************** +#include "AS.hpp" +#include "window.hpp" +#include "dsp/digital.hpp" + +struct TriggersMKIII: Module { + enum ParamIds { + TRIGGER_SWITCH_1, + TRIGGER_SWITCH_2, + NUM_PARAMS + }; + enum InputIds { + CV_TRIG_INPUT_1_1, + CV_TRIG_INPUT_1_2, + CV_TRIG_INPUT_2_1, + CV_TRIG_INPUT_2_2, + NUM_INPUTS + }; + enum OutputIds { + TRIGGER_OUT1, + TRIGGER_OUT2, + NUM_OUTPUTS + }; + enum LightIds { + TRIGGER_LED_1, + TRIGGER_LED_2, + NUM_LIGHTS + }; + + SchmittTrigger btnTrigger1, btnTrigger2; + SchmittTrigger extTrigger1_1, extTrigger1_2; + SchmittTrigger extTrigger2_1, extTrigger2_2; + + TextField* textField1; + TextField* textField2; + + const float lightLambda = 0.075f; + float resetLight1 = 0.0f; + float resetLight2 = 0.0f; + + int label_num1 = 0; + int label_num2 = 0; + + + + TriggersMKIII() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} + void step() override; + + + json_t *toJson()override { + json_t *rootJ = json_object(); + // text + json_object_set_new(rootJ, "label1", json_string(textField1->text.c_str())); + json_object_set_new(rootJ, "label2", json_string(textField2->text.c_str())); + return rootJ; + } + + void fromJson(json_t *rootJ)override { + json_t *text1J = json_object_get(rootJ, "label1"); + if (text1J){ + textField1->text = json_string_value(text1J); + } + json_t *text2J = json_object_get(rootJ, "label2"); + if (text2J){ + textField2->text = json_string_value(text2J); + } + } + +}; + +void TriggersMKIII::step() { + + outputs[TRIGGER_OUT1].value = 0.0f; + outputs[TRIGGER_OUT2].value = 0.0f; + + //TRIGGER 1 + if (btnTrigger1.process(params[TRIGGER_SWITCH_1].value) || extTrigger1_1.process(inputs[CV_TRIG_INPUT_1_1].value) || extTrigger1_2.process(inputs[CV_TRIG_INPUT_1_2].value)) { + resetLight1 = 1.0; + outputs[TRIGGER_OUT1].value = 10.0f; + }else{ + outputs[TRIGGER_OUT1].value = 0.0f; + } + resetLight1 -= resetLight1 / lightLambda / engineGetSampleRate(); + lights[TRIGGER_LED_1].value = resetLight1; + + //TRIGGER 2 + //EXTERNAL TRIGGER + if (btnTrigger2.process(params[TRIGGER_SWITCH_2].value) || extTrigger2_1.process(inputs[CV_TRIG_INPUT_2_1].value) || extTrigger2_2.process(inputs[CV_TRIG_INPUT_2_2].value)) { + resetLight2 = 1.0; + outputs[TRIGGER_OUT2].value = 10.0f; + //INTERNAL TRIGGER + }else{ + outputs[TRIGGER_OUT2].value = 0.0f; + } + resetLight2 -= resetLight2 / lightLambda / engineGetSampleRate(); + lights[TRIGGER_LED_2].value = resetLight2; + +} +//////////////////////////////////// +struct CustomLedDisplayTextField : TextField { + std::shared_ptr font; + Vec textOffset; + NVGcolor color; + CustomLedDisplayTextField(){ + font = Font::load(assetPlugin(plugin, "res/saxmono.ttf")); + color = nvgRGB(0xf0, 0x00, 0x00); + textOffset = Vec(5, 0); + }; + + void draw(NVGcontext *vg) override{ + nvgScissor(vg, 0, 0, box.size.x, box.size.y); + // Background + NVGcolor backgroundColor = nvgRGB(0x20, 0x10, 0x10); + NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10); + nvgBeginPath(vg); + nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 4.0); + + nvgFillColor(vg, backgroundColor); + nvgFill(vg); + nvgStrokeWidth(vg, 1.5); + nvgStrokeColor(vg, borderColor); + nvgStroke(vg); + nvgFontSize(vg, 20); + + // Text + if (font->handle >= 0) { + bndSetFont(font->handle); + + NVGcolor highlightColor = nvgRGB(0xf0, 0x00, 0x00);//color; + highlightColor.a = 0.5; + int begin = min(cursor, selection); + int end = (this == gFocusedWidget) ? max(cursor, selection) : -1; + bndIconLabelCaret(vg, textOffset.x, textOffset.y, + box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y, + -1, color, 12, text.c_str(), highlightColor, begin, end); + } + nvgResetScissor(vg); + bndSetFont(gGuiFont->handle); + } + + int getTextPosition(Vec mousePos)override { + bndSetFont(font->handle); + int textPos = bndIconLabelTextPosition(gVg, textOffset.x, textOffset.y, + box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y, + -1, 12, text.c_str(), mousePos.x, mousePos.y); + bndSetFont(font->handle); + return textPos; + } +}; + +//////////////////////////////////// + +struct TriggersMKIIIWidget : ModuleWidget { + + TextField* textField1; + TextField* textField2; + TriggersMKIIIWidget(TriggersMKIII *module); +}; + +TriggersMKIIIWidget::TriggersMKIIIWidget(TriggersMKIII *module) : ModuleWidget(module) { + + + setPanel(SVG::load(assetPlugin(plugin, "res/TriggersMKIII.svg"))); + + //SCREWS + addChild(Widget::create(Vec(RACK_GRID_WIDTH, 0))); + addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); + addChild(Widget::create(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + + static const float led_offset = 3.3; + static const float led_center = 15; + static const float y_offset = 150; + //TRIGGER 1 + + textField1 = Widget::create(Vec(6, 46)); + textField1->box.size = Vec(78, 30); + textField1->multiline = false; + addChild(textField1); + module->textField1 = this->textField1; + //SWITCH + addParam(ParamWidget::create(Vec(led_center, 122), module, TriggersMKIII::TRIGGER_SWITCH_1, 0.0, 1.0, 0.0)); + addChild(ModuleLightWidget::create>(Vec(led_center+led_offset, 122+led_offset), module, TriggersMKIII::TRIGGER_LED_1)); + //PORTS + addInput(Port::create(Vec(8, 90), Port::INPUT, module, TriggersMKIII::CV_TRIG_INPUT_1_1)); + addInput(Port::create(Vec(33, 90), Port::INPUT, module, TriggersMKIII::CV_TRIG_INPUT_1_2)); + addOutput(Port::create(Vec(58, 90), Port::OUTPUT, module, TriggersMKIII::TRIGGER_OUT1)); + + //TRIGGER 2 + textField2 = Widget::create(Vec(6, 46+y_offset)); + textField2->box.size = Vec(78, 30); + textField2->multiline = false; + addChild(textField2); + module->textField2 = this->textField2; + //SWITCH + addParam(ParamWidget::create(Vec(led_center, 122+y_offset), module, TriggersMKIII::TRIGGER_SWITCH_2, 0.0, 1.0, 0.0)); + addChild(ModuleLightWidget::create>(Vec(led_center+led_offset, 122+led_offset+y_offset), module, TriggersMKIII::TRIGGER_LED_2)); + //PORTS + addInput(Port::create(Vec(8, 90+y_offset), Port::INPUT, module, TriggersMKIII::CV_TRIG_INPUT_2_1)); + addInput(Port::create(Vec(33, 90+y_offset), Port::INPUT, module, TriggersMKIII::CV_TRIG_INPUT_2_2)); + addOutput(Port::create(Vec(58, 90+y_offset), Port::OUTPUT, module, TriggersMKIII::TRIGGER_OUT2)); + + +} + + +Model *modelTriggersMKIII = Model::create("AS", "TriggersMKIII", "Triggers MKIII", SWITCH_TAG, UTILITY_TAG);