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.

238 lines
7.1KB

  1. //**************************************************************************************
  2. //CV to Trigger convenrter module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS
  3. //
  4. //
  5. //**************************************************************************************
  6. #include "AS.hpp"
  7. #include "dsp/digital.hpp"
  8. struct ZeroCV2T : Module {
  9. enum ParamIds {
  10. TRIG_SWITCH_1,
  11. TRIG_SWITCH_2,
  12. TRIG_SWITCH_3,
  13. TRIG_SWITCH_4,
  14. NUM_PARAMS
  15. };
  16. enum InputIds {
  17. CV_IN_1,
  18. CV_IN_2,
  19. CV_IN_3,
  20. CV_IN_4,
  21. NUM_INPUTS
  22. };
  23. enum OutputIds {
  24. TRIG_OUT_1,
  25. TRIG_OUT_2,
  26. TRIG_OUT_3,
  27. TRIG_OUT_4,
  28. NUM_OUTPUTS
  29. };
  30. enum LightIds {
  31. TRIG_LED_1,
  32. TRIG_LED_2,
  33. TRIG_LED_3,
  34. TRIG_LED_4,
  35. NUM_LIGHTS
  36. };
  37. SchmittTrigger trig_1, trig_2, trig_3, trig_4;
  38. PulseGenerator trigPulse1, trigPulse2, trigPulse3, trigPulse4;
  39. bool trig_pulse_1 = false;
  40. bool trig_pulse_2 = false;
  41. bool trig_pulse_3 = false;
  42. bool trig_pulse_4 = false;
  43. float trigger_length = 0.0001f;
  44. const float lightLambda = 0.075f;
  45. float trigLight1 = 0.0f;
  46. float trigLight2 = 0.0f;
  47. float trigLight3 = 0.0f;
  48. float trigLight4 = 0.0f;
  49. bool cv_1_engaged = false;
  50. bool cv_2_engaged = false;
  51. bool cv_3_engaged = false;
  52. bool cv_4_engaged = false;
  53. float current_cv_1_volts = 0.0f;
  54. float current_cv_2_volts = 0.0f;
  55. float current_cv_3_volts = 0.0f;
  56. float current_cv_4_volts = 0.0f;
  57. float trigger_treshold = 0.0005f;
  58. ZeroCV2T() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  59. void step() override;
  60. };
  61. void ZeroCV2T::step() {
  62. //CV TRIG 1
  63. if ( trig_1.process( params[TRIG_SWITCH_1].value ) ) {
  64. trigLight1 = 1.0;
  65. trigPulse1.trigger( trigger_length );
  66. }
  67. current_cv_1_volts = inputs[CV_IN_1].value;
  68. if ( fabs( current_cv_1_volts ) < trigger_treshold ){
  69. if(!cv_1_engaged){
  70. cv_1_engaged = true;
  71. trigLight1 = 1.0;
  72. trigPulse1.trigger( trigger_length );
  73. // send trigger
  74. }
  75. } else {
  76. if ( fabs( current_cv_1_volts ) > trigger_treshold ) {
  77. // reenable trigger
  78. cv_1_engaged = false;
  79. }
  80. }
  81. trigLight1 -= trigLight1 / lightLambda / engineGetSampleRate();
  82. lights[TRIG_LED_1].value = trigLight1;
  83. trig_pulse_1 = trigPulse1.process( 1.0 / engineGetSampleRate() );
  84. outputs[TRIG_OUT_1].value = ( trig_pulse_1 ? 10.0f : 0.0f );
  85. //CV 2 TRIG 2
  86. if ( trig_2.process( params[TRIG_SWITCH_2].value ) ) {
  87. trigLight2 = 1.0;
  88. trigPulse2.trigger( trigger_length );
  89. }
  90. current_cv_2_volts = inputs[CV_IN_2].value;
  91. if ( fabs( current_cv_2_volts ) < trigger_treshold ){
  92. if(!cv_2_engaged){
  93. cv_2_engaged = true;
  94. trigLight2 = 1.0;
  95. trigPulse2.trigger( trigger_length );
  96. // send trigger
  97. }
  98. } else {
  99. if ( fabs( current_cv_2_volts ) > trigger_treshold ) {
  100. // reenable trigger
  101. cv_2_engaged = false;
  102. }
  103. }
  104. trigLight2 -= trigLight2 / lightLambda / engineGetSampleRate();
  105. lights[TRIG_LED_2].value = trigLight2;
  106. trig_pulse_2 = trigPulse2.process( 1.0 / engineGetSampleRate() );
  107. outputs[TRIG_OUT_2].value = ( trig_pulse_2 ? 10.0f : 0.0f );
  108. //CV 2 TRIG 3
  109. if ( trig_3.process( params[TRIG_SWITCH_3].value ) ) {
  110. trigLight3 = 1.0;
  111. trigPulse3.trigger( trigger_length );
  112. }
  113. current_cv_3_volts = inputs[CV_IN_3].value;
  114. if ( fabs( current_cv_3_volts ) < trigger_treshold ){
  115. if(!cv_3_engaged){
  116. cv_3_engaged = true;
  117. trigLight3 = 1.0;
  118. trigPulse3.trigger( trigger_length );
  119. // send trigger
  120. }
  121. } else {
  122. if ( fabs( current_cv_3_volts ) > trigger_treshold ) {
  123. // reenable trigger
  124. cv_3_engaged = false;
  125. }
  126. }
  127. trigLight3 -= trigLight3 / lightLambda / engineGetSampleRate();
  128. lights[TRIG_LED_3].value = trigLight3;
  129. trig_pulse_3 = trigPulse3.process( 1.0 / engineGetSampleRate() );
  130. outputs[TRIG_OUT_3].value = ( trig_pulse_3 ? 10.0f : 0.0f );
  131. //CV 2 TRIG 4
  132. if ( trig_4.process( params[TRIG_SWITCH_4].value ) ) {
  133. trigLight4 = 1.0;
  134. trigPulse4.trigger( trigger_length );
  135. }
  136. current_cv_4_volts = inputs[CV_IN_4].value;
  137. if ( fabs( current_cv_4_volts ) < trigger_treshold ){
  138. if(!cv_4_engaged){
  139. cv_4_engaged = true;
  140. trigLight4 = 1.0;
  141. trigPulse4.trigger( trigger_length );
  142. // send trigger
  143. }
  144. } else {
  145. if ( fabs( current_cv_4_volts ) > trigger_treshold ) {
  146. // reenable trigger
  147. cv_4_engaged = false;
  148. }
  149. }
  150. trigLight4 -= trigLight4 / lightLambda / engineGetSampleRate();
  151. lights[TRIG_LED_4].value = trigLight4;
  152. trig_pulse_4 = trigPulse4.process( 1.0 / engineGetSampleRate() );
  153. outputs[TRIG_OUT_4].value = ( trig_pulse_4 ? 10.0f : 0.0f );
  154. }
  155. struct ZeroCV2TWidget : ModuleWidget
  156. {
  157. ZeroCV2TWidget(ZeroCV2T *module);
  158. };
  159. ZeroCV2TWidget::ZeroCV2TWidget(ZeroCV2T *module) : ModuleWidget(module) {
  160. setPanel(SVG::load(assetPlugin(plugin, "res/ZeroCV2T.svg")));
  161. //SCREWS - SPECIAL SPACING FOR RACK WIDTH*4
  162. addChild(Widget::create<as_HexScrew>(Vec(0, 0)));
  163. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - RACK_GRID_WIDTH, 0)));
  164. addChild(Widget::create<as_HexScrew>(Vec(0, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  165. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  166. const int gp_offset = 75;
  167. //CV 2 TRIG 1
  168. //SWITCH & LED
  169. addParam(ParamWidget::create<LEDBezel>(Vec(6, 101), module, ZeroCV2T::TRIG_SWITCH_1 , 0.0f, 1.0f, 0.0f));
  170. addChild(ModuleLightWidget::create<LedLight<RedLight>>(Vec(6+2.2, 103.2), module, ZeroCV2T::TRIG_LED_1));
  171. //INPUTS
  172. addInput(Port::create<as_PJ301MPort>(Vec(18,60), Port::INPUT, module, ZeroCV2T::CV_IN_1));
  173. //OUTPUTS
  174. addOutput(Port::create<as_PJ301MPort>(Vec(32, 100), Port::OUTPUT, module, ZeroCV2T::TRIG_OUT_1));
  175. //CV 2 TRIG 2
  176. //SWITCH & LED
  177. addParam(ParamWidget::create<LEDBezel>(Vec(6, 101+gp_offset*1), module, ZeroCV2T::TRIG_SWITCH_2 , 0.0f, 1.0f, 0.0f));
  178. addChild(ModuleLightWidget::create<LedLight<RedLight>>(Vec(6+2.2, 103.2+gp_offset*1), module, ZeroCV2T::TRIG_LED_2));
  179. //INPUTS
  180. addInput(Port::create<as_PJ301MPort>(Vec(18,60+gp_offset*1), Port::INPUT, module, ZeroCV2T::CV_IN_2));
  181. //OUTPUTS
  182. addOutput(Port::create<as_PJ301MPort>(Vec(32, 100+gp_offset*1), Port::OUTPUT, module, ZeroCV2T::TRIG_OUT_2));
  183. //CV 2 TRIG 3
  184. //SWITCH & LED
  185. addParam(ParamWidget::create<LEDBezel>(Vec(6, 101+gp_offset*2), module, ZeroCV2T::TRIG_SWITCH_3 , 0.0f, 1.0f, 0.0f));
  186. addChild(ModuleLightWidget::create<LedLight<RedLight>>(Vec(6+2.2, 103.2+gp_offset*2), module, ZeroCV2T::TRIG_LED_3));
  187. //INPUTS
  188. addInput(Port::create<as_PJ301MPort>(Vec(18,60+gp_offset*2), Port::INPUT, module, ZeroCV2T::CV_IN_3));
  189. //OUTPUTS
  190. addOutput(Port::create<as_PJ301MPort>(Vec(32, 100+gp_offset*2), Port::OUTPUT, module, ZeroCV2T::TRIG_OUT_3));
  191. //CV 2 TRIG 4
  192. //SWITCH & LED
  193. addParam(ParamWidget::create<LEDBezel>(Vec(6, 101+gp_offset*3), module, ZeroCV2T::TRIG_SWITCH_4 , 0.0f, 1.0f, 0.0f));
  194. addChild(ModuleLightWidget::create<LedLight<RedLight>>(Vec(6+2.2, 103.2+gp_offset*3), module, ZeroCV2T::TRIG_LED_4));
  195. //INPUTS
  196. addInput(Port::create<as_PJ301MPort>(Vec(18,60+gp_offset*3), Port::INPUT, module, ZeroCV2T::CV_IN_4));
  197. //OUTPUTS
  198. addOutput(Port::create<as_PJ301MPort>(Vec(32, 100+gp_offset*3), Port::OUTPUT, module, ZeroCV2T::TRIG_OUT_4));
  199. }
  200. RACK_PLUGIN_MODEL_INIT(AS, ZeroCV2T) {
  201. Model *modelZeroCV2T = Model::create<ZeroCV2T, ZeroCV2TWidget>("AS", "ZeroCV2T", "Zero Crossing CV to Trigger Switch", SWITCH_TAG);
  202. return modelZeroCV2T;
  203. }