You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
6.8KB

  1. //**************************************************************************************
  2. //TriggersMKIMKI module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS
  3. //
  4. //**************************************************************************************
  5. #include "AS.hpp"
  6. #include "dsp/digital.hpp"
  7. #include <sstream>
  8. #include <iomanip>
  9. struct TriggersMKI: Module {
  10. enum ParamIds {
  11. VOLTAGE_PARAM,
  12. RUN_SWITCH,
  13. MOMENTARY_SWITCH,
  14. NUM_PARAMS
  15. };
  16. enum InputIds {
  17. CV_RUN_INPUT,
  18. NUM_INPUTS
  19. };
  20. enum OutputIds {
  21. TRIGGER_OUT,
  22. NUM_OUTPUTS
  23. };
  24. enum LightIds {
  25. RUN_LED,
  26. MOMENTARY_LED,
  27. NUM_LIGHTS
  28. };
  29. SchmittTrigger LatchTrigger;
  30. SchmittTrigger LatchExtTrigger;
  31. SchmittTrigger BtnTrigger;
  32. SchmittTrigger BtnExtTrigger;
  33. const float lightLambda = 0.075;
  34. float resetLight = 0.0f;
  35. float volts = 0.0f;
  36. bool running = false;
  37. float display_volts = 0.0f;
  38. bool negative_volts = false;
  39. PulseGenerator triggerPulse;
  40. bool trg_pulse = false;
  41. TriggersMKI() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  42. void step() override;
  43. json_t *toJson() override
  44. {
  45. json_t *rootJ = json_object();
  46. json_t *button_statesJ = json_array();
  47. json_t *button_stateJ = json_integer((int)running);
  48. json_array_append_new(button_statesJ, button_stateJ);
  49. json_object_set_new(rootJ, "run", button_statesJ);
  50. return rootJ;
  51. }
  52. void fromJson(json_t *rootJ) override
  53. {
  54. json_t *button_statesJ = json_object_get(rootJ, "run");
  55. if (button_statesJ)
  56. {
  57. json_t *button_stateJ = json_array_get(button_statesJ,0);
  58. if (button_stateJ)
  59. running = !!json_integer_value(button_stateJ);
  60. }
  61. }
  62. };
  63. void TriggersMKI::step() {
  64. display_volts = 0.0f;
  65. volts = params[VOLTAGE_PARAM].value;
  66. display_volts = volts;
  67. negative_volts = false;
  68. if(volts< 0.0){
  69. negative_volts = true;
  70. }
  71. if(negative_volts){
  72. display_volts = - display_volts;
  73. //doesn't update fast enough to get rid of the negative 0 display color
  74. /*
  75. if(display_volts == -0.0){
  76. display_volts = 0.0;
  77. }
  78. */
  79. }else{
  80. display_volts = volts;
  81. }
  82. //LATCH TRIGGER
  83. //EXTERNAL TRIGGER
  84. if (LatchTrigger.process(params[RUN_SWITCH].value)||LatchExtTrigger.process(inputs[CV_RUN_INPUT].value)) {
  85. running = !running;
  86. }
  87. //INTERNAL TRIGGER
  88. if (running) {
  89. lights[RUN_LED].value = 1.0f;
  90. outputs[TRIGGER_OUT].value = volts;
  91. }else{
  92. lights[RUN_LED].value = 0.0f;
  93. outputs[TRIGGER_OUT].value = 0.0f;
  94. }
  95. //MOMENTARY TRIGGER
  96. //updated to use pulses
  97. if (BtnTrigger.process(params[MOMENTARY_SWITCH].value)) {
  98. resetLight = 1.0;
  99. if (!running) {
  100. triggerPulse.trigger(1e-3f);
  101. }
  102. }
  103. if(!running){
  104. trg_pulse = triggerPulse.process(1.0 / engineGetSampleRate());
  105. outputs[TRIGGER_OUT].value = (trg_pulse ? volts : 0.0f);
  106. }
  107. resetLight -= resetLight / lightLambda / engineGetSampleRate();
  108. lights[MOMENTARY_LED].value = resetLight;
  109. }
  110. ///////////////////////////////////
  111. struct VoltsDisplayWidget : TransparentWidget {
  112. float *value;
  113. bool *negative;
  114. std::shared_ptr<Font> font;
  115. VoltsDisplayWidget() {
  116. font = Font::load(assetPlugin(plugin, "res/Segment7Standard.ttf"));
  117. };
  118. void draw(NVGcontext *vg) override {
  119. // Background
  120. //NVGcolor backgroundColor = nvgRGB(0x20, 0x20, 0x20);
  121. NVGcolor backgroundColor = nvgRGB(0x20, 0x10, 0x10);
  122. NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10);
  123. nvgBeginPath(vg);
  124. nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 4.0);
  125. nvgFillColor(vg, backgroundColor);
  126. nvgFill(vg);
  127. nvgStrokeWidth(vg, 1.5);
  128. nvgStrokeColor(vg, borderColor);
  129. nvgStroke(vg);
  130. // text
  131. nvgFontSize(vg, 18);
  132. nvgFontFaceId(vg, font->handle);
  133. nvgTextLetterSpacing(vg, 2.5);
  134. char display_string[10];
  135. sprintf(display_string,"%5.2f",*value);
  136. Vec textPos = Vec(3.0f, 17.0f);
  137. NVGcolor textColor = nvgRGB(0xdf, 0xd2, 0x2c);
  138. nvgFillColor(vg, nvgTransRGBA(textColor, 16));
  139. nvgText(vg, textPos.x, textPos.y, "~~~~~", NULL);
  140. textColor = nvgRGB(0xda, 0xe9, 0x29);
  141. nvgFillColor(vg, nvgTransRGBA(textColor, 16));
  142. nvgText(vg, textPos.x, textPos.y, "\\\\\\\\\\", NULL);
  143. if(*negative){
  144. textColor = nvgRGB(0xf0, 0x00, 0x00);
  145. }else{
  146. //textColor = nvgRGB(0x90, 0xc6, 0x3e);
  147. textColor = nvgRGB(0x00, 0xaf, 0x25);
  148. }
  149. nvgFillColor(vg, textColor);
  150. nvgText(vg, textPos.x, textPos.y, display_string, NULL);
  151. }
  152. };
  153. ////////////////////////////////////
  154. struct TriggersMKIWidget : ModuleWidget
  155. {
  156. TriggersMKIWidget(TriggersMKI *module);
  157. };
  158. TriggersMKIWidget::TriggersMKIWidget(TriggersMKI *module) : ModuleWidget(module) {
  159. setPanel(SVG::load(assetPlugin(plugin, "res/TriggersMKI.svg")));
  160. //SCREWS
  161. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, 0)));
  162. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  163. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  164. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  165. //VOLTS DISPLAY
  166. VoltsDisplayWidget *display1 = new VoltsDisplayWidget();
  167. display1->box.pos = Vec(10,50);
  168. display1->box.size = Vec(70, 20);
  169. display1->value = &module->display_volts;
  170. display1->negative = &module->negative_volts;
  171. addChild(display1);
  172. //PARAMS
  173. addParam(ParamWidget::create<as_KnobBlack>(Vec(26, 77), module, TriggersMKI::VOLTAGE_PARAM, -10.0f, 10.0f, 0.0f));
  174. //SWITCHES
  175. static const float led_offset = 3.3;
  176. static const float led_center = 15;
  177. addParam(ParamWidget::create<BigLEDBezel>(Vec(led_center, 182), module, TriggersMKI::RUN_SWITCH, 0.0, 1.0, 0.0));
  178. addChild(ModuleLightWidget::create<GiantLight<RedLight>>(Vec(led_center+led_offset, 182+led_offset), module, TriggersMKI::RUN_LED));
  179. addParam(ParamWidget::create<BigLEDBezel>(Vec(led_center, 262), module, TriggersMKI::MOMENTARY_SWITCH, 0.0, 1.0, 0.0));
  180. addChild(ModuleLightWidget::create<GiantLight<RedLight>>(Vec(led_center+led_offset, 262+led_offset), module, TriggersMKI::MOMENTARY_LED));
  181. //PORTS
  182. addInput(Port::create<as_PJ301MPort>(Vec(10, 145), Port::INPUT, module, TriggersMKI::CV_RUN_INPUT));
  183. addOutput(Port::create<as_PJ301MPort>(Vec(55, 145), Port::OUTPUT, module, TriggersMKI::TRIGGER_OUT));
  184. }
  185. RACK_PLUGIN_MODEL_INIT(AS, TriggersMKI) {
  186. Model *modelTriggersMKI = Model::create<TriggersMKI, TriggersMKIWidget>("AS", "TriggersMKI", "Triggers MKI", SWITCH_TAG, UTILITY_TAG);
  187. return modelTriggersMKI;
  188. }