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.

280 lines
13KB

  1. #include "plugin.hpp"
  2. struct SEQ3 : Module {
  3. enum ParamIds {
  4. PARAM_CLOCK,
  5. PARAM_RUN,
  6. PARAM_RESET,
  7. PARAM_STEPS,
  8. ENUMS(PARAM_ROW1, 8),
  9. ENUMS(PARAM_ROW2, 8),
  10. ENUMS(PARAM_ROW3, 8),
  11. ENUMS(PARAM_GATE, 8),
  12. NUM_PARAMS
  13. };
  14. enum InputIds {
  15. INPUT_CLOCK,
  16. INPUT_EXT_CLOCK,
  17. INPUT_RESET,
  18. INPUT_STEPS,
  19. NUM_INPUTS
  20. };
  21. enum OutputIds {
  22. OUTPUT_GATES,
  23. OUTPUT_ROW1,
  24. OUTPUT_ROW2,
  25. OUTPUT_ROW3,
  26. ENUMS(OUTPUT_GATE, 8),
  27. NUM_OUTPUTS
  28. };
  29. enum LightIds {
  30. LIGHT_RUN,
  31. LIGHT_RESET,
  32. LIGHT_GATES,
  33. LIGHT_ROW1,
  34. LIGHT_ROW2,
  35. LIGHT_ROW3,
  36. ENUMS(LIGHT_GATE, 8),
  37. NUM_LIGHTS
  38. };
  39. bool running = true;
  40. dsp::SchmittTrigger clockTrigger;
  41. dsp::SchmittTrigger runningTrigger;
  42. dsp::SchmittTrigger resetTrigger;
  43. dsp::SchmittTrigger gateTriggers[8];
  44. /** Phase of internal LFO */
  45. float phase = 0.f;
  46. int index = 0;
  47. bool gates[8] = {};
  48. SEQ3() {
  49. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  50. configParam(PARAM_CLOCK, -2.f, 6.f, 2.f, "Clock tempo", " bpm", 2.f, 60.f);
  51. configParam(PARAM_RUN, 0.f, 1.f, 0.f, "Run");
  52. configParam(PARAM_RESET, 0.f, 1.f, 0.f, "Reset");
  53. configParam(PARAM_STEPS, 1.f, 8.f, 8.f, "Steps");
  54. paramQuantities[PARAM_STEPS]->snapEnabled = true;
  55. for (int i = 0; i < 8; i++)
  56. configParam(PARAM_ROW1 + i, 0.f, 10.f, 0.f, string::f("Row 1 step %d", i + 1));
  57. for (int i = 0; i < 8; i++)
  58. configParam(PARAM_ROW2 + i, 0.f, 10.f, 0.f, string::f("Row 2 step %d", i + 1));
  59. for (int i = 0; i < 8; i++)
  60. configParam(PARAM_ROW3 + i, 0.f, 10.f, 0.f, string::f("Row 3 step %d", i + 1));
  61. for (int i = 0; i < 8; i++)
  62. configParam(PARAM_GATE + i, 0.f, 1.f, 0.f, string::f("Gate step %d", i + 1));
  63. configInput(INPUT_CLOCK, "Clock rate");
  64. configInput(INPUT_EXT_CLOCK, "External clock");
  65. configInput(INPUT_RESET, "Reset");
  66. configInput(INPUT_STEPS, "Steps");
  67. configOutput(OUTPUT_GATES, "Gate");
  68. configOutput(OUTPUT_ROW1, "Row 1");
  69. configOutput(OUTPUT_ROW2, "Row 2");
  70. configOutput(OUTPUT_ROW3, "Row 3");
  71. for (int i = 0; i < 8; i++)
  72. configOutput(OUTPUT_GATE + i, string::f("Gate %d", i + 1));
  73. onReset();
  74. }
  75. void onReset() override {
  76. for (int i = 0; i < 8; i++) {
  77. gates[i] = true;
  78. }
  79. }
  80. void onRandomize() override {
  81. for (int i = 0; i < 8; i++) {
  82. gates[i] = (random::uniform() > 0.5f);
  83. }
  84. }
  85. json_t* dataToJson() override {
  86. json_t* rootJ = json_object();
  87. // running
  88. json_object_set_new(rootJ, "running", json_boolean(running));
  89. // gates
  90. json_t* gatesJ = json_array();
  91. for (int i = 0; i < 8; i++) {
  92. json_array_insert_new(gatesJ, i, json_integer((int) gates[i]));
  93. }
  94. json_object_set_new(rootJ, "gates", gatesJ);
  95. return rootJ;
  96. }
  97. void dataFromJson(json_t* rootJ) override {
  98. // running
  99. json_t* runningJ = json_object_get(rootJ, "running");
  100. if (runningJ)
  101. running = json_is_true(runningJ);
  102. // gates
  103. json_t* gatesJ = json_object_get(rootJ, "gates");
  104. if (gatesJ) {
  105. for (int i = 0; i < 8; i++) {
  106. json_t* gateJ = json_array_get(gatesJ, i);
  107. if (gateJ)
  108. gates[i] = !!json_integer_value(gateJ);
  109. }
  110. }
  111. }
  112. void setIndex(int index) {
  113. int numSteps = (int) clamp(std::round(params[PARAM_STEPS].getValue() + inputs[INPUT_STEPS].getVoltage()), 1.f, 8.f);
  114. phase = 0.f;
  115. this->index = index;
  116. if (this->index >= numSteps)
  117. this->index = 0;
  118. }
  119. void process(const ProcessArgs& args) override {
  120. // Run
  121. if (runningTrigger.process(params[PARAM_RUN].getValue())) {
  122. running = !running;
  123. }
  124. bool gateIn = false;
  125. if (running) {
  126. if (inputs[INPUT_EXT_CLOCK].isConnected()) {
  127. // External clock
  128. if (clockTrigger.process(inputs[INPUT_EXT_CLOCK].getVoltage())) {
  129. setIndex(index + 1);
  130. }
  131. gateIn = clockTrigger.isHigh();
  132. }
  133. else {
  134. // Internal clock
  135. float clockTime = std::pow(2.f, params[PARAM_CLOCK].getValue() + inputs[INPUT_CLOCK].getVoltage());
  136. phase += clockTime * args.sampleTime;
  137. if (phase >= 1.f) {
  138. setIndex(index + 1);
  139. }
  140. gateIn = (phase < 0.5f);
  141. }
  142. }
  143. // Reset
  144. if (resetTrigger.process(params[PARAM_RESET].getValue() + inputs[INPUT_RESET].getVoltage())) {
  145. setIndex(0);
  146. }
  147. // Gate buttons
  148. for (int i = 0; i < 8; i++) {
  149. if (gateTriggers[i].process(params[PARAM_GATE + i].getValue())) {
  150. gates[i] = !gates[i];
  151. }
  152. outputs[OUTPUT_GATE + i].setVoltage((running && gateIn && i == index && gates[i]) ? 10.f : 0.f);
  153. lights[LIGHT_GATE + i].setSmoothBrightness((gateIn && i == index) ? (gates[i] ? 1.f : 0.33) : (gates[i] ? 0.66 : 0.0), args.sampleTime);
  154. }
  155. // Outputs
  156. outputs[OUTPUT_ROW1].setVoltage(params[PARAM_ROW1 + index].getValue());
  157. outputs[OUTPUT_ROW2].setVoltage(params[PARAM_ROW2 + index].getValue());
  158. outputs[OUTPUT_ROW3].setVoltage(params[PARAM_ROW3 + index].getValue());
  159. outputs[OUTPUT_GATES].setVoltage((gateIn && gates[index]) ? 10.f : 0.f);
  160. lights[LIGHT_RUN].setBrightness(running);
  161. lights[LIGHT_RESET].setSmoothBrightness(resetTrigger.isHigh(), args.sampleTime);
  162. lights[LIGHT_GATES].setSmoothBrightness(gateIn, args.sampleTime);
  163. lights[LIGHT_ROW1].setBrightness(outputs[OUTPUT_ROW1].getVoltage() / 10.f);
  164. lights[LIGHT_ROW2].setBrightness(outputs[OUTPUT_ROW2].getVoltage() / 10.f);
  165. lights[LIGHT_ROW3].setBrightness(outputs[OUTPUT_ROW3].getVoltage() / 10.f);
  166. }
  167. };
  168. struct SEQ3Widget : ModuleWidget {
  169. SEQ3Widget(SEQ3* module) {
  170. setModule(module);
  171. setPanel(createPanel(asset::plugin(pluginInstance, "res/SEQ3.svg")));
  172. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  173. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  174. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  175. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  176. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(10.381, 23.626)), module, SEQ3::PARAM_CLOCK));
  177. addParam(createParamCentered<LEDButton>(mm2px(Vec(23.38, 23.538)), module, SEQ3::PARAM_RUN));
  178. addParam(createParamCentered<LEDButton>(mm2px(Vec(36.38, 23.538)), module, SEQ3::PARAM_RESET));
  179. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(49.381, 23.626)), module, SEQ3::PARAM_STEPS));
  180. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(10.381, 57.712)), module, SEQ3::PARAM_ROW1 + 0));
  181. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(23.38, 57.712)), module, SEQ3::PARAM_ROW1 + 1));
  182. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(36.38, 57.712)), module, SEQ3::PARAM_ROW1 + 2));
  183. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(49.381, 57.712)), module, SEQ3::PARAM_ROW1 + 3));
  184. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(62.38, 57.712)), module, SEQ3::PARAM_ROW1 + 4));
  185. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(75.381, 57.712)), module, SEQ3::PARAM_ROW1 + 5));
  186. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(88.38, 57.712)), module, SEQ3::PARAM_ROW1 + 6));
  187. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(101.38, 57.712)), module, SEQ3::PARAM_ROW1 + 7));
  188. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(10.381, 71.734)), module, SEQ3::PARAM_ROW2 + 0));
  189. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(23.38, 71.734)), module, SEQ3::PARAM_ROW2 + 1));
  190. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(36.38, 71.734)), module, SEQ3::PARAM_ROW2 + 2));
  191. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(49.381, 71.734)), module, SEQ3::PARAM_ROW2 + 3));
  192. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(62.38, 71.734)), module, SEQ3::PARAM_ROW2 + 4));
  193. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(75.381, 71.734)), module, SEQ3::PARAM_ROW2 + 5));
  194. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(88.38, 71.734)), module, SEQ3::PARAM_ROW2 + 6));
  195. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(101.38, 71.734)), module, SEQ3::PARAM_ROW2 + 7));
  196. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(10.381, 85.711)), module, SEQ3::PARAM_ROW3 + 0));
  197. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(23.38, 85.711)), module, SEQ3::PARAM_ROW3 + 1));
  198. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(36.38, 85.711)), module, SEQ3::PARAM_ROW3 + 2));
  199. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(49.381, 85.711)), module, SEQ3::PARAM_ROW3 + 3));
  200. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(62.38, 85.711)), module, SEQ3::PARAM_ROW3 + 4));
  201. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(75.381, 85.711)), module, SEQ3::PARAM_ROW3 + 5));
  202. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(88.38, 85.711)), module, SEQ3::PARAM_ROW3 + 6));
  203. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(101.38, 85.711)), module, SEQ3::PARAM_ROW3 + 7));
  204. addParam(createParamCentered<LEDButton>(mm2px(Vec(10.381, 96.945)), module, SEQ3::PARAM_GATE + 0));
  205. addParam(createParamCentered<LEDButton>(mm2px(Vec(23.381, 96.945)), module, SEQ3::PARAM_GATE + 1));
  206. addParam(createParamCentered<LEDButton>(mm2px(Vec(36.38, 96.945)), module, SEQ3::PARAM_GATE + 2));
  207. addParam(createParamCentered<LEDButton>(mm2px(Vec(49.381, 96.945)), module, SEQ3::PARAM_GATE + 3));
  208. addParam(createParamCentered<LEDButton>(mm2px(Vec(62.381, 96.945)), module, SEQ3::PARAM_GATE + 4));
  209. addParam(createParamCentered<LEDButton>(mm2px(Vec(75.381, 96.945)), module, SEQ3::PARAM_GATE + 5));
  210. addParam(createParamCentered<LEDButton>(mm2px(Vec(88.381, 96.945)), module, SEQ3::PARAM_GATE + 6));
  211. addParam(createParamCentered<LEDButton>(mm2px(Vec(101.38, 96.945)), module, SEQ3::PARAM_GATE + 7));
  212. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(10.381, 37.331)), module, SEQ3::INPUT_CLOCK));
  213. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(23.38, 37.331)), module, SEQ3::INPUT_EXT_CLOCK));
  214. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(36.38, 37.331)), module, SEQ3::INPUT_RESET));
  215. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(49.381, 37.331)), module, SEQ3::INPUT_STEPS));
  216. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(62.38, 37.329)), module, SEQ3::OUTPUT_GATES));
  217. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(75.38, 37.329)), module, SEQ3::OUTPUT_ROW1));
  218. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(88.38, 37.329)), module, SEQ3::OUTPUT_ROW2));
  219. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(101.381, 37.329)), module, SEQ3::OUTPUT_ROW3));
  220. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(10.381, 107.865)), module, SEQ3::OUTPUT_GATE + 0));
  221. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(23.38, 107.865)), module, SEQ3::OUTPUT_GATE + 1));
  222. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(36.38, 107.865)), module, SEQ3::OUTPUT_GATE + 2));
  223. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(49.381, 107.865)), module, SEQ3::OUTPUT_GATE + 3));
  224. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(62.38, 107.865)), module, SEQ3::OUTPUT_GATE + 4));
  225. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(75.38, 107.865)), module, SEQ3::OUTPUT_GATE + 5));
  226. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(88.38, 107.865)), module, SEQ3::OUTPUT_GATE + 6));
  227. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(101.381, 107.865)), module, SEQ3::OUTPUT_GATE + 7));
  228. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(23.38, 23.538)), module, SEQ3::LIGHT_RUN));
  229. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(36.38, 23.538)), module, SEQ3::LIGHT_RESET));
  230. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(62.38, 23.538)), module, SEQ3::LIGHT_GATE));
  231. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(75.38, 23.538)), module, SEQ3::LIGHT_ROW1));
  232. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(88.38, 23.538)), module, SEQ3::LIGHT_ROW2));
  233. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(101.381, 23.538)), module, SEQ3::LIGHT_ROW3));
  234. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(10.381, 96.945)), module, SEQ3::LIGHT_GATE + 0));
  235. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(23.381, 96.945)), module, SEQ3::LIGHT_GATE + 1));
  236. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(36.38, 96.945)), module, SEQ3::LIGHT_GATE + 2));
  237. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(49.381, 96.945)), module, SEQ3::LIGHT_GATE + 3));
  238. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(62.381, 96.945)), module, SEQ3::LIGHT_GATE + 4));
  239. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(75.381, 96.945)), module, SEQ3::LIGHT_GATE + 5));
  240. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(88.381, 96.945)), module, SEQ3::LIGHT_GATE + 6));
  241. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(101.38, 96.945)), module, SEQ3::LIGHT_GATE + 7));
  242. }
  243. };
  244. Model* modelSEQ3 = createModel<SEQ3, SEQ3Widget>("SEQ3");