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.

222 lines
6.7KB

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