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.

288 lines
9.3KB

  1. #include "ML_modules.hpp"
  2. #include "dsp/digital.hpp"
  3. namespace rack_plugin_ML_modules {
  4. struct SeqSwitch : Module {
  5. enum ParamIds {
  6. NUM_STEPS,
  7. STEP1_PARAM,
  8. STEP2_PARAM,
  9. STEP3_PARAM,
  10. STEP4_PARAM,
  11. STEP5_PARAM,
  12. STEP6_PARAM,
  13. STEP7_PARAM,
  14. STEP8_PARAM,
  15. NUM_PARAMS
  16. };
  17. enum InputIds {
  18. IN1_INPUT,
  19. IN2_INPUT,
  20. IN3_INPUT,
  21. IN4_INPUT,
  22. IN5_INPUT,
  23. IN6_INPUT,
  24. IN7_INPUT,
  25. IN8_INPUT,
  26. POS_INPUT,
  27. TRIGUP_INPUT,
  28. TRIGDN_INPUT,
  29. RESET_INPUT,
  30. NUMSTEPS_INPUT,
  31. NUM_INPUTS
  32. };
  33. enum OutputIds {
  34. OUT1_OUTPUT,
  35. NUM_OUTPUTS
  36. };
  37. enum LightIds {
  38. STEP1_LIGHT,
  39. STEP2_LIGHT,
  40. STEP3_LIGHT,
  41. STEP4_LIGHT,
  42. STEP5_LIGHT,
  43. STEP6_LIGHT,
  44. STEP7_LIGHT,
  45. STEP8_LIGHT,
  46. NUM_LIGHTS
  47. };
  48. SeqSwitch() : Module( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS ) { reset(); };
  49. void step() override;
  50. int position=0;
  51. const float in_min[4] = {0.0, 0.0, 0.0, -5.0};
  52. const float in_max[4] = {8.0, 6.0, 10.0, 5.0};
  53. SchmittTrigger upTrigger, downTrigger, resetTrigger, stepTriggers[8];
  54. enum InputRange {
  55. Zero_Eight,
  56. Zero_Six,
  57. Zero_Ten,
  58. MinusFive_Five
  59. };
  60. json_t *toJson() override {
  61. json_t *rootJ = json_object();
  62. // outMode:
  63. json_object_set_new(rootJ, "inputRange", json_integer(inputRange));
  64. return rootJ;
  65. };
  66. void fromJson(json_t *rootJ) override {
  67. // outMode:
  68. json_t *inputRangeJ = json_object_get(rootJ, "inputRange");
  69. if(inputRangeJ) inputRange = (InputRange) json_integer_value(inputRangeJ);
  70. };
  71. InputRange inputRange = Zero_Eight;
  72. void reset() override {
  73. position = 0;
  74. for(int i=0; i<8; i++) lights[i].value = 0.0;
  75. };
  76. };
  77. void SeqSwitch::step() {
  78. float out=0.0;
  79. int numSteps = round(clamp(params[NUM_STEPS].value,1.0f,8.0f));
  80. if( inputs[NUMSTEPS_INPUT].active ) numSteps = round(clamp(inputs[NUMSTEPS_INPUT].value,1.0f,8.0f));
  81. if( inputs[POS_INPUT].active ) {
  82. // position = round( clamp( inputs[POS_INPUT].value,0.0f,8.0f))/8.0f * (numSteps-1) ;
  83. float in_value = clamp( inputs[POS_INPUT].value,in_min[inputRange],in_max[inputRange] );
  84. position = round( rescale( in_value, in_min[inputRange], in_max[inputRange], 0.0f, 1.0f*(numSteps-1) ) );
  85. } else {
  86. if( inputs[TRIGUP_INPUT].active ) {
  87. if (upTrigger.process(inputs[TRIGUP_INPUT].value) ) position++;
  88. }
  89. if( inputs[TRIGDN_INPUT].active ) {
  90. if (downTrigger.process(inputs[TRIGDN_INPUT].value) ) position--;
  91. }
  92. if( inputs[RESET_INPUT].active ) {
  93. if (resetTrigger.process(inputs[RESET_INPUT].value) ) position = 0;
  94. }
  95. };
  96. for(int i=0; i<numSteps; i++) {
  97. if( stepTriggers[i].process(params[STEP1_PARAM+i].value)) position = i;
  98. };
  99. while( position < 0 ) position += numSteps;
  100. while( position >= numSteps ) position -= numSteps;
  101. out = inputs[IN1_INPUT+position].normalize(0.0);
  102. for(int i=0; i<8; i++) lights[i].value = (i==position)?1.0:0.0;
  103. outputs[OUT1_OUTPUT].value = out;
  104. };
  105. struct SeqSwitchRangeItem : MenuItem {
  106. SeqSwitch *seqSwitch;
  107. SeqSwitch::InputRange inputRange;
  108. void onAction(EventAction &e) override {
  109. seqSwitch->inputRange = inputRange;
  110. };
  111. void step() override {
  112. rightText = (seqSwitch->inputRange == inputRange)? "✔" : "";
  113. };
  114. };
  115. struct SeqSwitchWidget : ModuleWidget {
  116. SeqSwitchWidget(SeqSwitch *module);
  117. json_t *toJsonData() ;
  118. void fromJsonData(json_t *root) ;
  119. Menu *createContextMenu() override;
  120. };
  121. Menu *SeqSwitchWidget::createContextMenu() {
  122. Menu *menu = ModuleWidget::createContextMenu();
  123. MenuLabel *spacerLabel = new MenuLabel();
  124. menu->addChild(spacerLabel);
  125. SeqSwitch *seqSwitch = dynamic_cast<SeqSwitch*>(module);
  126. assert(seqSwitch);
  127. MenuLabel *modeLabel2 = new MenuLabel();
  128. modeLabel2->text = "Input Range";
  129. menu->addChild(modeLabel2);
  130. SeqSwitchRangeItem *zeroEightItem = new SeqSwitchRangeItem();
  131. zeroEightItem->text = "0 - 8V";
  132. zeroEightItem->seqSwitch = seqSwitch;
  133. zeroEightItem->inputRange = SeqSwitch::Zero_Eight;
  134. menu->addChild(zeroEightItem);
  135. SeqSwitchRangeItem *zeroSixItem = new SeqSwitchRangeItem();
  136. zeroSixItem->text = "0 - 6V";
  137. zeroSixItem->seqSwitch = seqSwitch;
  138. zeroSixItem->inputRange = SeqSwitch::Zero_Six;
  139. menu->addChild(zeroSixItem);
  140. SeqSwitchRangeItem *zeroTenItem = new SeqSwitchRangeItem();
  141. zeroTenItem->text = "0 - 10V";
  142. zeroTenItem->seqSwitch = seqSwitch;
  143. zeroTenItem->inputRange = SeqSwitch::Zero_Ten;
  144. menu->addChild(zeroTenItem);
  145. SeqSwitchRangeItem *fiveFiveItem = new SeqSwitchRangeItem();
  146. fiveFiveItem->text = "-5 - 5V";
  147. fiveFiveItem->seqSwitch = seqSwitch;
  148. fiveFiveItem->inputRange = SeqSwitch::MinusFive_Five;;
  149. menu->addChild(fiveFiveItem);
  150. return menu;
  151. };
  152. SeqSwitchWidget::SeqSwitchWidget(SeqSwitch *module) : ModuleWidget(module) {
  153. box.size = Vec(15*8, 380);
  154. {
  155. SVGPanel *panel = new SVGPanel();
  156. panel->box.size = box.size;
  157. panel->setBackground(SVG::load(assetPlugin(plugin,"res/SeqSwitch.svg")));
  158. addChild(panel);
  159. }
  160. addChild(Widget::create<MLScrew>(Vec(15, 0)));
  161. addChild(Widget::create<MLScrew>(Vec(box.size.x-30, 0)));
  162. addChild(Widget::create<MLScrew>(Vec(15, 365)));
  163. addChild(Widget::create<MLScrew>(Vec(box.size.x-30, 365)));
  164. addParam(ParamWidget::create<RedSnapMLKnob>(Vec(14, 63), module, SeqSwitch::NUM_STEPS, 1.0, 8.0, 8.0));
  165. addInput(Port::create<MLPort>(Vec(81, 64), Port::INPUT, module, SeqSwitch::NUMSTEPS_INPUT));
  166. addInput(Port::create<MLPort>(Vec(9, 272), Port::INPUT, module, SeqSwitch::TRIGUP_INPUT));
  167. addInput(Port::create<MLPort>(Vec(47, 272), Port::INPUT, module, SeqSwitch::RESET_INPUT));
  168. addInput(Port::create<MLPort>(Vec(85, 272), Port::INPUT, module, SeqSwitch::TRIGDN_INPUT));
  169. const float offset_y = 118, delta_y=38;
  170. addInput(Port::create<MLPort>(Vec(32, offset_y + 0*delta_y), Port::INPUT, module, SeqSwitch::IN1_INPUT));
  171. addInput(Port::create<MLPort>(Vec(32, offset_y + 1*delta_y), Port::INPUT, module, SeqSwitch::IN2_INPUT));
  172. addInput(Port::create<MLPort>(Vec(32, offset_y + 2*delta_y), Port::INPUT, module, SeqSwitch::IN3_INPUT));
  173. addInput(Port::create<MLPort>(Vec(32, offset_y + 3*delta_y), Port::INPUT, module, SeqSwitch::IN4_INPUT));
  174. addInput(Port::create<MLPort>(Vec(62, offset_y + 0*delta_y), Port::INPUT, module, SeqSwitch::IN5_INPUT));
  175. addInput(Port::create<MLPort>(Vec(62, offset_y + 1*delta_y), Port::INPUT, module, SeqSwitch::IN6_INPUT));
  176. addInput(Port::create<MLPort>(Vec(62, offset_y + 2*delta_y), Port::INPUT, module, SeqSwitch::IN7_INPUT));
  177. addInput(Port::create<MLPort>(Vec(62, offset_y + 3*delta_y), Port::INPUT, module, SeqSwitch::IN8_INPUT));
  178. addParam(ParamWidget::create<ML_MediumLEDButton>(Vec(11, offset_y + 3 + 0*delta_y), module, SeqSwitch::STEP1_PARAM, 0.0, 1.0, 0.0));
  179. addParam(ParamWidget::create<ML_MediumLEDButton>(Vec(11, offset_y + 3 + 1*delta_y), module, SeqSwitch::STEP2_PARAM, 0.0, 1.0, 0.0));
  180. addParam(ParamWidget::create<ML_MediumLEDButton>(Vec(11, offset_y + 3 + 2*delta_y), module, SeqSwitch::STEP3_PARAM, 0.0, 1.0, 0.0));
  181. addParam(ParamWidget::create<ML_MediumLEDButton>(Vec(11, offset_y + 3 + 3*delta_y), module, SeqSwitch::STEP4_PARAM, 0.0, 1.0, 0.0));
  182. addParam(ParamWidget::create<ML_MediumLEDButton>(Vec(89, offset_y + 3 + 0*delta_y), module, SeqSwitch::STEP5_PARAM, 0.0, 1.0, 0.0));
  183. addParam(ParamWidget::create<ML_MediumLEDButton>(Vec(89, offset_y + 3 + 1*delta_y), module, SeqSwitch::STEP6_PARAM, 0.0, 1.0, 0.0));
  184. addParam(ParamWidget::create<ML_MediumLEDButton>(Vec(89, offset_y + 3 + 2*delta_y), module, SeqSwitch::STEP7_PARAM, 0.0, 1.0, 0.0));
  185. addParam(ParamWidget::create<ML_MediumLEDButton>(Vec(89, offset_y + 3 + 3*delta_y), module, SeqSwitch::STEP8_PARAM, 0.0, 1.0, 0.0));
  186. addChild(ModuleLightWidget::create<MLMediumLight<GreenLight>>(Vec(15, offset_y + 7 + 0*delta_y), module, SeqSwitch::STEP1_LIGHT));
  187. addChild(ModuleLightWidget::create<MLMediumLight<GreenLight>>(Vec(15, offset_y + 7 + 1*delta_y), module, SeqSwitch::STEP2_LIGHT));
  188. addChild(ModuleLightWidget::create<MLMediumLight<GreenLight>>(Vec(15, offset_y + 7 + 2*delta_y), module, SeqSwitch::STEP3_LIGHT));
  189. addChild(ModuleLightWidget::create<MLMediumLight<GreenLight>>(Vec(15, offset_y + 7 + 3*delta_y), module, SeqSwitch::STEP4_LIGHT));
  190. addChild(ModuleLightWidget::create<MLMediumLight<GreenLight>>(Vec(93, offset_y + 7 + 0*delta_y), module, SeqSwitch::STEP5_LIGHT));
  191. addChild(ModuleLightWidget::create<MLMediumLight<GreenLight>>(Vec(93, offset_y + 7 + 1*delta_y), module, SeqSwitch::STEP6_LIGHT));
  192. addChild(ModuleLightWidget::create<MLMediumLight<GreenLight>>(Vec(93, offset_y + 7 + 2*delta_y), module, SeqSwitch::STEP7_LIGHT));
  193. addChild(ModuleLightWidget::create<MLMediumLight<GreenLight>>(Vec(93, offset_y + 7 + 3*delta_y), module, SeqSwitch::STEP8_LIGHT));
  194. addInput(Port::create<MLPort>( Vec(19, 318), Port::INPUT, module, SeqSwitch::POS_INPUT));
  195. addOutput(Port::create<MLPort>(Vec(75, 318), Port::OUTPUT, module, SeqSwitch::OUT1_OUTPUT));
  196. }
  197. } // namespace rack_plugin_ML_modules
  198. using namespace rack_plugin_ML_modules;
  199. RACK_PLUGIN_MODEL_INIT(ML_modules, SeqSwitch) {
  200. Model *modelSeqSwitch = Model::create<SeqSwitch, SeqSwitchWidget>("ML modules", "SeqSwitch", "Sequential Switch 8->1",SWITCH_TAG, SEQUENCER_TAG);
  201. return modelSeqSwitch;
  202. }